Ejemplo n.º 1
0
   void ValuePrinterInfo::Init(clang::QualType Ty) {
    assert(!Ty.isNull() && "Type must be valid!");
    assert(m_Context && "ASTContext cannot be null!");

    assert(sizeof(m_Type) >= sizeof(clang::QualType) && "m_Type too small!");
    m_Type = *reinterpret_cast<void**>(&Ty);

    // 1. Get the flags
    if (Ty.isLocalConstQualified() || Ty.isConstant(*m_Context)){
      m_Flags |= VPI_Const;
    }

    if (Ty->isPointerType()) {
      // treat arrary-to-pointer decay as array:
      QualType PQT = Ty->getPointeeType();
      const Type* PTT = PQT.getTypePtr();
      if (!PTT || !PTT->isArrayType()) {
        m_Flags |= VPI_Ptr;
        if (const RecordType* RT = dyn_cast<RecordType>(Ty.getTypePtr()))
          if (RecordDecl* RD = RT->getDecl()) {
            CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD);
            if (CRD && CRD->isPolymorphic())
              m_Flags |= VPI_Polymorphic;
          }
      }
    }
  }
Ejemplo n.º 2
0
std::string GetTypeAsString(const clang::QualType &type) {
	std::stringstream stream;
	std::string name = type.getAsString();
    // If it is an anonymous structure, print all the fields recursively
    if (name.substr(0,11) == "struct (ano") {
        stream << "struct { ";
		clang::RecordDecl* struct_decl = type.getTypePtr()->getAsStructureType()->getDecl();
		// Print the types of all the fields
        for (const auto* field : struct_decl->fields()) {
			std::string type = GetTypeAsString(field->getType().getCanonicalType());
			std::string name = field->getName();
            stream << type;
            stream << " " << name << "; ";
        }
        stream << "}";
	} else if (type.getTypePtr()->isBooleanType()) {
		return "bool";
	} else {
        stream << type.getAsString(); //just print the type
    }
	return stream.str();
}
insieme::core::TypePtr VariableLengthArrayExtension::Visit(const clang::QualType& type, insieme::frontend::conversion::Converter& converter) {
    // we iterate trough the dimensions of the array from left to right. There is no hint
    // in the C standard how this should be handled and therefore the normal operator precedence is used.
    if(const clang::VariableArrayType* arrType = llvm::dyn_cast<clang::VariableArrayType>(type.getTypePtr())) {
        // check if we already converted this decl
        if(::containsKey(arrayTypeMap, arrType)) return arrayTypeMap[arrType];

        // only consider variable array types
        // create a decl stmt e.g., decl uint v1 = i;
        core::IRBuilder builder = converter.getIRBuilder();
        auto index = converter.convertExpr(arrType->getSizeExpr());
        // cast needed from rhs type to int<inf>?!
        if(index->getType() != builder.getLangBasic().getUIntInf()) {
            index = builder.numericCast(index, builder.getLangBasic().getUIntInf());
        }
        auto decl = builder.declarationStmt(builder.getLangBasic().getUIntInf(), index);
        sizes.push_back(decl);

        // convert the element type (in nested array case this is again a variable array type)
        core::TypePtr elementType = converter.convertType(arrType->getElementType());
        core::TypePtr arrayType = builder.arrayType(elementType, decl->getVariable());

        // add type to map
        arrayTypeMap[arrType] = arrayType;
        return arrayType;
    }
    return nullptr;
}
void RSExportReduce::analyzeResultType(StateOfAnalyzeTranslationUnit &S) {
  if (!(S.FnAccumulatorOk && S.FnOutConverterOk)) {
    // No idea what the result type is
    slangAssert(!S.Ok);
    return;
  }

  struct ResultInfoType {
    const clang::QualType QType;
    clang::VarDecl *const Decl;
    const char *FnKey;
    const std::string &FnName;
    std::function<std::string ()> UnlessOutConverter;
  } ResultInfo =
        S.FnOutConverter
        ? ResultInfoType({ S.FnOutConverterParamFirstTy, S.FnOutConverterParamFirst,
                           KeyOutConverter, mNameOutConverter,
                           []() { return std::string(""); }})
        : ResultInfoType({ S.FnAccumulatorParamFirstTy,  S.FnAccumulatorParamFirst,
                           KeyAccumulator,  mNameAccumulator,
                           []() { return std::string(" unless ") + KeyOutConverter + " is provided"; }});
  const clang::QualType PointeeQType = ResultInfo.QType->getPointeeType();

  if (PointeeQType->isPointerType()) {
    S.RSC.ReportError(ResultInfo.Decl->getLocation(),
                      "%0 parameter '%1' (type '%2') must not point to a pointer%3")
        << S.DiagnosticDescription(ResultInfo.FnKey, ResultInfo.FnName)
        << ResultInfo.Decl->getName() << ResultInfo.QType.getAsString()
        << ResultInfo.UnlessOutConverter();
  } else if (PointeeQType->isIncompleteType()) {
    S.RSC.ReportError(ResultInfo.Decl->getLocation(),
                      "%0 parameter '%1' (type '%2') must not point to an incomplete type%3")
        << S.DiagnosticDescription(ResultInfo.FnKey, ResultInfo.FnName)
        << ResultInfo.Decl->getName() << ResultInfo.QType.getAsString()
        << ResultInfo.UnlessOutConverter();
  } else if (HasRSObjectType(PointeeQType.getTypePtr())) {
    S.RSC.ReportError(ResultInfo.Decl->getLocation(),
                      "%0 parameter '%1' (type '%2') must not point to data containing an object type%3")
        << S.DiagnosticDescription(ResultInfo.FnKey, ResultInfo.FnName)
        << ResultInfo.Decl->getName() << ResultInfo.QType.getAsString()
        << ResultInfo.UnlessOutConverter();
  } else if (RSExportType::ValidateType(&S.RSC, S.ASTC, PointeeQType,
                                        ResultInfo.Decl, ResultInfo.Decl->getLocStart(),
                                        S.RSC.getTargetAPI(),
                                        false /* IsFilterscript */,
                                        true /* IsExtern */)) {
    // TODO: Better diagnostics on validation or creation failure?
    if ((mResultType = RSExportType::Create(&S.RSC, PointeeQType.getTypePtr(),
                                            NotLegacyKernelArgument, ResultInfo.Decl)) != nullptr) {
      const RSExportType *CheckType = mResultType;
      const char *ArrayErrorPhrase = "";
      if (mResultType->getClass() == RSExportType::ExportClassConstantArray) {
        CheckType = static_cast<const RSExportConstantArrayType *>(mResultType)->getElementType();
        ArrayErrorPhrase = "n array of";
      }
      switch (CheckType->getClass()) {
        case RSExportType::ExportClassMatrix:
          // Not supported for now -- what does a matrix result type mean?
          S.RSC.ReportError(ResultInfo.Decl->getLocation(),
                            "%0 parameter '%1' (type '%2') must not point to a%3 matrix type%4")
              << S.DiagnosticDescription(ResultInfo.FnKey, ResultInfo.FnName)
              << ResultInfo.Decl->getName() << ResultInfo.QType.getAsString()
              << ArrayErrorPhrase
              << ResultInfo.UnlessOutConverter();
          mResultType = nullptr;
          break;
        default:
          // All's well
          break;
      }
    }
  }

  if (mResultType)
    S.RSC.insertExportReduceResultType(mResultType);
  else
    S.Ok = false;
}
// Process "void mNameAccumulator(compType *accum, in1Type in1, …, inNType inN[, specialarguments])"
void RSExportReduce::analyzeAccumulator(StateOfAnalyzeTranslationUnit &S) {
  slangAssert(S.FnAccumulator);

  // Must return void
  checkVoidReturn(S, FN_IDENT_ACCUMULATOR, S.FnAccumulator);

  // Must have initial parameter of same type as initializer parameter
  // (if there is an initializer), followed by at least 1 input

  if (S.FnAccumulator->getNumParams() < 2) {
    S.RSC.ReportError(S.FnAccumulator->getLocation(),
                      "%0 must take at least 2 parameters")
        << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator);
    S.Ok = S.FnAccumulatorOk = false;
    return;
  }

  S.FnAccumulatorParamFirst = S.FnAccumulator->getParamDecl(0);
  S.FnAccumulatorParamFirstTy = S.FnAccumulatorParamFirst->getType().getCanonicalType();

  // First parameter must be of pointer type
  if (!S.FnAccumulatorParamFirstTy->isPointerType()) {
    S.RSC.ReportError(S.FnAccumulator->getLocation(),
                      "%0 parameter '%1' must be of pointer type not '%2'")
        << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator)
        << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString();
    S.Ok = S.FnAccumulatorOk = false;
    return;
  }

  // If there is an initializer with a pointer-typed parameter (as
  // opposed to an initializer with a bad parameter list), then
  // accumulator first parameter must be of same type as initializer
  // parameter
  if (S.FnInitializer &&
      !S.FnInitializerParamTy.isNull() &&
      S.FnInitializerParamTy->isPointerType() &&
      !S.FnAccumulator->getASTContext().hasSameUnqualifiedType(
          S.FnInitializerParamTy->getPointeeType().getCanonicalType(),
          S.FnAccumulatorParamFirstTy->getPointeeType().getCanonicalType())) {
    // <accumulator> parameter '<baz>' (type '<tbaz>') and initializer <goo>() parameter '<gaz>' (type '<tgaz>')
    //   must be pointers to the same type
    S.RSC.ReportError(S.FnAccumulator->getLocation(),
                      "%0 parameter '%1' (type '%2') and %3 %4() parameter '%5' (type '%6')"
                      " must be pointers to the same type")
        << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator)
        << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString()
        << KeyInitializer << mNameInitializer
        << S.FnInitializerParam->getName() << S.FnInitializerParamTy.getAsString();
    S.Ok = S.FnAccumulatorOk = false;
  }

  if (S.FnAccumulatorOk && S.FnAccumulatorParamFirstTy->getPointeeType()->isFunctionType()) {
    S.RSC.ReportError(S.FnAccumulator->getLocation(),
                      "%0 parameter '%1' (type '%2') must not be pointer to function type")
        << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator)
        << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString();
    S.Ok = S.FnAccumulatorOk = false;
  }

  if (S.FnAccumulatorOk && S.FnAccumulatorParamFirstTy->getPointeeType()->isIncompleteType()) {
    S.RSC.ReportError(S.FnAccumulator->getLocation(),
                      "%0 parameter '%1' (type '%2') must not be pointer to incomplete type")
        << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator)
        << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString();
    S.Ok = S.FnAccumulatorOk = false;
  }

  if (S.FnAccumulatorOk &&
      HasRSObjectType(S.FnAccumulatorParamFirstTy->getPointeeType().getCanonicalType().getTypePtr())) {
    S.RSC.ReportError(S.FnAccumulator->getLocation(),
                      "%0 parameter '%1' (type '%2') must not be pointer to data containing an object type")
        << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator)
        << S.FnAccumulatorParamFirst->getName() << S.FnAccumulatorParamFirstTy.getAsString();
    S.Ok = S.FnAccumulatorOk = false;
  }

  // Parameter must not point to const-qualified
  checkPointeeConstQualified(S, FN_IDENT_ACCUMULATOR, mNameAccumulator, S.FnAccumulatorParamFirst, false);

  // Analyze special parameters
  S.Ok &= (S.FnAccumulatorOk &= processSpecialKernelParameters(
                                  &S.RSC,
                                  std::bind(S.DiagnosticDescription, KeyAccumulator, mNameAccumulator),
                                  S.FnAccumulator,
                                  &S.FnAccumulatorIndexOfFirstSpecialParameter,
                                  &mAccumulatorSignatureMetadata));

  // Must have at least an accumulator and an input.
  // If we get here we know there are at least 2 arguments; so the only problem case is
  // where we have an accumulator followed immediately by a special parameter.
  if (S.FnAccumulatorIndexOfFirstSpecialParameter < 2) {
    slangAssert(S.FnAccumulatorIndexOfFirstSpecialParameter < S.FnAccumulator->getNumParams());
    S.RSC.ReportError(S.FnAccumulator->getLocation(),
                      "%0 must have at least 1 input ('%1' is a special parameter)")
        << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator)
        << S.FnAccumulator->getParamDecl(S.FnAccumulatorIndexOfFirstSpecialParameter)->getName();
    S.Ok = S.FnAccumulatorOk = false;
    return;
  }

  if (S.FnAccumulatorOk) {
    mAccumulatorSignatureMetadata |= bcinfo::MD_SIG_In;
    mAccumulatorTypeSize = S.ASTC.getTypeSizeInChars(S.FnAccumulatorParamFirstTy->getPointeeType()).getQuantity();
    for (size_t ParamIdx = 1; ParamIdx < S.FnAccumulatorIndexOfFirstSpecialParameter; ++ParamIdx) {
      const clang::ParmVarDecl *const Param = S.FnAccumulator->getParamDecl(ParamIdx);
      mAccumulatorIns.push_back(Param);
      const clang::QualType ParamQType = Param->getType().getCanonicalType();
      const clang::Type *ParamType = ParamQType.getTypePtr();

      RSExportType *ParamEType = nullptr;
      if (ParamQType->isPointerType()) {
        S.RSC.ReportError(Param->getLocation(),
                          "%0 parameter '%1' (type '%2') must not be a pointer")
            << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator)
            << Param->getName() << ParamQType.getAsString();
        S.Ok = false;
      } else if (HasRSObjectType(ParamType)) {
        S.RSC.ReportError(Param->getLocation(),
                          "%0 parameter '%1' (type '%2') must not contain an object type")
            << S.DiagnosticDescription(KeyAccumulator, mNameAccumulator)
            << Param->getName() << ParamQType.getAsString();
        S.Ok = false;
      } else if (RSExportType::ValidateType(&S.RSC, S.ASTC, ParamQType, Param, Param->getLocStart(),
                                            S.RSC.getTargetAPI(),
                                            false /* IsFilterscript */,
                                            true /* IsExtern */)) {
        // TODO: Better diagnostics on validation or creation failure?
        ParamEType = RSExportType::Create(&S.RSC, ParamType, NotLegacyKernelArgument);
        S.Ok &= (ParamEType != nullptr);
      } else {
        S.Ok = false;
      }
      mAccumulatorInTypes.push_back(ParamEType); // possibly nullptr
    }
  }
}