Esempio n. 1
0
/**
 * Check if two calls are a send/recv pair.
 *
 * @param sendCall
 * @param recvCall
 *
 * @return if they are send/recv pair
 */
bool MPICheckerAST::isSendRecvPair(const MPICall &sendCall,
                                   const MPICall &recvCall) const {
    if (!funcClassifier_.isSendType(sendCall)) return false;
    if (!funcClassifier_.isRecvType(recvCall)) return false;
    if (!areDatatypesEqual(sendCall, recvCall)) return false;

    // compare count, tag
    for (const size_t idx : {MPIPointToPoint::kCount, MPIPointToPoint::kTag}) {
        if (!sendCall.arguments()[idx].isEqual(recvCall.arguments()[idx])) {
            return false;
        }
    }

    // compare ranks
    const auto &rankArgSend = sendCall.arguments()[MPIPointToPoint::kRank];
    const auto &rankArgRecv = recvCall.arguments()[MPIPointToPoint::kRank];

    if (rankArgSend.typeSequence().size() != rankArgRecv.typeSequence().size())
        return false;

    // build sequences without last operator(skip first element)
    std::vector<ArgumentVisitor::ComponentType> seq1, seq2;
    std::vector<std::string> val1, val2;
    bool containsSubtraction{false};
    for (size_t i = 1; i < rankArgSend.typeSequence().size(); ++i) {
        seq1.push_back(rankArgSend.typeSequence()[i]);
        val1.push_back(rankArgSend.valueSequence()[i]);
        seq2.push_back(rankArgRecv.typeSequence()[i]);
        val2.push_back(rankArgRecv.valueSequence()[i]);
        if (rankArgSend.valueSequence()[i] == "-") containsSubtraction = true;
        if (rankArgRecv.valueSequence()[i] == "-") containsSubtraction = true;
    }

    if (containsSubtraction) {
        // check ordered
        if (seq1 != seq2 || val1 != val2) return false;
    } else {
        // check permutation
        if ((!cont::isPermutation(seq1, seq2)) ||
            (!cont::isPermutation(val1, val2))) {
            return false;
        }
    }
    // last (value|var|function) must be identical
    if (val1.back() != val2.back()) return false;

    // last operator must be inverse
    if (!rankArgSend.isLastOperatorInverse(rankArgRecv)) return false;

    return true;
}
Esempio n. 2
0
/**
 * Checks if mpi-datatypes for 2 different point to point calls are equal.
 *
 * @param sendCall
 * @param recvCall
 *
 * @return equality
 */
bool MPICheckerAST::areDatatypesEqual(const MPICall &sendCall,
                                      const MPICall &recvCall) const {
    // compare mpi datatype
    llvm::StringRef sendDataType = util::sourceRangeAsStringRef(
        sendCall.arguments()[MPIPointToPoint::kDatatype]
            .stmt_->getSourceRange(),
        analysisManager_);

    llvm::StringRef recvDataType = util::sourceRangeAsStringRef(
        recvCall.arguments()[MPIPointToPoint::kDatatype]
            .stmt_->getSourceRange(),
        analysisManager_);

    return sendDataType == recvDataType;
}
Esempio n. 3
0
/**
 * Checks if buffer type and specified mpi datatype matches.
 *
 * @param mpiCall call to check type correspondence for
 */
void MPICheckerAST::checkBufferTypeMatch(const MPICall &mpiCall) const {
    // one pair consists of {bufferIdx, mpiDatatypeIdx}
    IndexPairs indexPairs = bufferDataTypeIndices(mpiCall);

    // for every buffer mpi-data pair in function
    // check if their types match
    for (const auto &idxPair : indexPairs) {
        const VarDecl *bufferArg =
            mpiCall.arguments()[idxPair.first].vars().front();

        // collect buffer type information
        const mpi::TypeVisitor typeVisitor{bufferArg->getType()};

        // get mpi datatype as string
        auto mpiDatatype = mpiCall.arguments()[idxPair.second].stmt_;
        StringRef mpiDatatypeString{util::sourceRangeAsStringRef(
            mpiDatatype->getSourceRange(), analysisManager_)};

        selectTypeMatcher(typeVisitor, mpiCall, mpiDatatypeString, idxPair);
    }
}
Esempio n. 4
0
/**
 * Check if invalid argument types are used in a mpi call.
 * This check looks at indices where only integer values are valid.
 * (count, rank, tag) Any non integer type usage is reported.
 *
 * @param mpiCall to check the arguments for
 */
void MPICheckerAST::checkForInvalidArgs(const MPICall &mpiCall) const {
    std::vector<size_t> indicesToCheck = integerIndices(mpiCall);
    if (!indicesToCheck.size()) return;

    // iterate indices which should not have integer arguments
    for (const size_t idx : indicesToCheck) {
        // check for invalid variable types
        const auto &arg = mpiCall.arguments()[idx];
        const auto &vars = arg.vars();
        for (const auto &var : vars) {
            const mpi::TypeVisitor typeVisitor{var->getType()};
            if (!typeVisitor.builtinType() ||
                !typeVisitor.builtinType()->isIntegerType()) {
                bugReporter_.reportInvalidArgumentType(
                    mpiCall.callExpr(), idx, var->getSourceRange(), "Variable");
            }
        }

        // check for float literals
        if (arg.floatingLiterals().size()) {
            bugReporter_.reportInvalidArgumentType(
                mpiCall.callExpr(), idx,
                arg.floatingLiterals().front()->getSourceRange(), "Literal");
        }

        // check for invalid return types from functions
        const auto &functions = arg.functions();
        for (const auto &function : functions) {
            const mpi::TypeVisitor typeVisitor{function->getReturnType()};
            if (!typeVisitor.builtinType() ||
                !typeVisitor.builtinType()->isIntegerType()) {
                bugReporter_.reportInvalidArgumentType(
                    mpiCall.callExpr(), idx, function->getSourceRange(),
                    "Return value");
            }
        }
    }
}