Ejemplo n.º 1
0
const ReachingDefinitions &DataflowAnalyzer::computeReachingDefinitions(const Term *term,
                                                                        const MemoryLocation &memoryLocation,
                                                                        const ReachingDefinitions &definitions) {
    auto &termDefinitions = dataflow().getDefinitions(term);

    if (isTracked(memoryLocation)) {
        definitions.project(memoryLocation, termDefinitions);
    } else {
        termDefinitions.clear();
    }

    return termDefinitions;
}
 static void resize( state_type &x1 ,
                     state_type x2 )
 {
     //std::cout << "resizing..." << std::endl;
     // allocate required memory
     x1.resize( x2.size() );
     for( size_t i=0 ; i < x2.size() ; ++i )
     {
         x1[i] = dataflow( unwrap([]( shared_vec v2 )
                           {
                               shared_vec tmp = std::allocate_shared<dvecvec>( std::allocator<dvecvec>() );
                               tmp->resize( v2->size() );
                               for( size_t n=0 ; n<v2->size() ; ++n )
                                   (*tmp)[n].resize( (*v2)[n].size() );
                               return tmp;
                           }) ,
                           x2[i] );
     }
     //std::cout << "resizing complete" << std::endl;
 }
Ejemplo n.º 3
0
const MemoryLocation &DataflowAnalyzer::computeMemoryLocation(const Term *term, const ReachingDefinitions &definitions) {
    return dataflow().setMemoryLocation(term, [&]() -> MemoryLocation {
        switch (term->kind()) {
            case Term::MEMORY_LOCATION_ACCESS: {
                return term->asMemoryLocationAccess()->memoryLocation();
            }
            case Term::DEREFERENCE: {
                auto dereference = term->asDereference();
                auto addressValue = computeValue(dereference->address(), definitions);

                if (addressValue->abstractValue().isConcrete()) {
                    if (dereference->domain() == MemoryDomain::MEMORY) {
                        return MemoryLocation(
                            dereference->domain(),
                            addressValue->abstractValue().asConcrete().value() * CHAR_BIT,
                            dereference->size());
                    } else {
                        return MemoryLocation(
                            dereference->domain(),
                            addressValue->abstractValue().asConcrete().value(),
                            dereference->size());
                    }
                } else if (addressValue->isStackOffset()) {
                    return MemoryLocation(MemoryDomain::STACK, addressValue->stackOffset() * CHAR_BIT, dereference->size());
                } else {
                    return MemoryLocation();
                }
                break;
            }
            default: {
                log_.warning(tr("%1: Term kind %2 cannot have a memory location.").arg(Q_FUNC_INFO).arg(term->kind()));
                return MemoryLocation();
            }
        }
    }());
}
Ejemplo n.º 4
0
        static typename util::detail::algorithm_result<ExPolicy, SegIter>::type
        segmented_for_each(Algo && algo, ExPolicy const& policy,
            SegIter first, SegIter last, F && f, Proj && proj,
            boost::mpl::false_)
        {
            typedef hpx::traits::segmented_iterator_traits<SegIter> traits;
            typedef typename traits::segment_iterator segment_iterator;
            typedef typename traits::local_iterator local_iterator_type;
            typedef util::detail::algorithm_result<ExPolicy, SegIter> result;

            typedef typename std::iterator_traits<SegIter>::iterator_category
                iterator_category;
            typedef typename boost::mpl::bool_<boost::is_same<
                    iterator_category, std::input_iterator_tag
                >::value> forced_seq;

            segment_iterator sit = traits::segment(first);
            segment_iterator send = traits::segment(last);

            std::vector<future<local_iterator_type> > segments;
            segments.reserve(std::distance(sit, send));

            if (sit == send)
            {
                // all elements are on the same partition
                local_iterator_type beg = traits::local(first);
                local_iterator_type end = traits::local(last);
                if (beg != end)
                {
                    segments.push_back(dispatch_async(traits::get_id(sit),
                        algo, policy, forced_seq(), beg, end, f, proj
                    ));
                }
            }
            else {
                // handle the remaining part of the first partition
                local_iterator_type beg = traits::local(first);
                local_iterator_type end = traits::end(sit);
                if (beg != end)
                {
                    segments.push_back(dispatch_async(traits::get_id(sit),
                        algo, policy, forced_seq(), beg, end, f, proj
                    ));
                }

                // handle all of the full partitions
                for (++sit; sit != send; ++sit)
                {
                    beg = traits::begin(sit);
                    end = traits::end(sit);
                    if (beg != end)
                    {
                        segments.push_back(dispatch_async(traits::get_id(sit),
                            algo, policy, forced_seq(), beg, end, f, proj
                        ));
                    }
                }

                // handle the beginning of the last partition
                beg = traits::begin(sit);
                end = traits::local(last);
                if (beg != end)
                {
                    segments.push_back(dispatch_async(traits::get_id(sit),
                        algo, policy, forced_seq(), beg, end, f, proj
                    ));
                }
            }

            return result::get(
                dataflow(
                    [=](std::vector<hpx::future<local_iterator_type> > && r)
                        ->  SegIter
                    {
                        // handle any remote exceptions, will throw on error
                        std::list<boost::exception_ptr> errors;
                        parallel::util::detail::handle_remote_exceptions<
                            ExPolicy
                        >::call(r, errors);
                        return traits::compose(send, r.back().get());
                    },
                    std::move(segments)));
        }
Ejemplo n.º 5
0
    void jacobi( size_t n , size_t iterations, size_t block_size, std::string output_filename) {
        hpx::util::high_resolution_timer t;

        vector< vector< vector< shared_future<block> > > > blockList(2);
        jacobi_init(blockList, n, block_size);

        size_t numBlocks = blockList[0].size();

        for(size_t i = 1; i < iterations; ++i) {
            const size_t prev = i%2;
            const size_t curr = (i+1)%2;
            blockList[curr][0][0] = dataflow(
                    jacobi_BL, blockList[prev][0][0],
                               blockList[prev][0][1],
                               blockList[prev][1][0] );
            for(size_t j = 1; j < numBlocks - 1; j++) {
                blockList[curr][j][0] = dataflow(
                        jacobi_left, blockList[prev][j  ][0],
                                     blockList[prev][j  ][1],
                                     blockList[prev][j-1][0],
                                     blockList[prev][j+1][0] );
            }
            blockList[curr][numBlocks-1][0] = dataflow(
                    jacobi_TL, blockList[prev][numBlocks-1][0],
                               blockList[prev][numBlocks-1][1],
                               blockList[prev][numBlocks-2][0] );

            for(size_t j = 1; j < numBlocks - 1; j++) {
                blockList[curr][0][j] = dataflow(
                        jacobi_bot, blockList[prev][0][j  ], 
                                    blockList[prev][0][j-1],
                                    blockList[prev][0][j+1],
                                    blockList[prev][1][j  ] );
                for(size_t k = 1; k < numBlocks - 1; k++) {
                    blockList[curr][j][k] = dataflow( 
                            jacobi_op, blockList[prev][k  ][j  ],
                                       blockList[prev][k  ][j-1],
                                       blockList[prev][k  ][j+1],
                                       blockList[prev][k-1][j  ],
                                       blockList[prev][k+1][j  ]);
                }
                blockList[curr][numBlocks-1][j] = dataflow(
                        jacobi_top, blockList[prev][numBlocks-1][j  ], 
                                    blockList[prev][numBlocks-1][j-1],
                                    blockList[prev][numBlocks-1][j+1],
                                    blockList[prev][numBlocks-2][j  ] );
            }
            blockList[curr][0][numBlocks-1] = dataflow(
                    jacobi_BR, blockList[prev][0][numBlocks-1],
                               blockList[prev][0][numBlocks-2],
                               blockList[prev][1][numBlocks-1]);
            for(size_t j = 1; j < numBlocks - 1; j++) {
            blockList[curr][j][numBlocks-1] = dataflow(
                    jacobi_left, blockList[prev][j ][numBlocks-1],
                                 blockList[prev][j ][numBlocks-2],
                                 blockList[prev][j-1][numBlocks-1],
                                 blockList[prev][j+1][numBlocks-1]);
            }
            blockList[curr][numBlocks-1][numBlocks-1] = dataflow(
                    jacobi_TR, blockList[prev][numBlocks-1][numBlocks-1],
                               blockList[prev][numBlocks-1][numBlocks-2],
                               blockList[prev][numBlocks-2][numBlocks-1]);
        }
        for(int i = 0; i < blockList[(n-1)%2].size(); i++) {
            hpx::wait_all(blockList[(n-1)%2][i]);
        }

        report_timing(n, iterations, t.elapsed());
        //output_grid(output_filename, *grid_old, n);
   }
Ejemplo n.º 6
0
        static typename util::detail::algorithm_result<ExPolicy, SegIter>::type
        segmented_minormax(Algo && algo, ExPolicy const& policy,
            SegIter first, SegIter last, F && f, Proj && proj, std::false_type)
        {
            typedef hpx::traits::segmented_iterator_traits<SegIter> traits;
            typedef typename traits::segment_iterator segment_iterator;
            typedef typename traits::local_iterator local_iterator_type;

            typedef std::integral_constant<bool,
                    !hpx::traits::is_forward_iterator<SegIter>::value
                > forced_seq;
            typedef util::detail::algorithm_result<ExPolicy, SegIter> result;

            segment_iterator sit = traits::segment(first);
            segment_iterator send = traits::segment(last);

            std::vector<future<SegIter> > segments;
            segments.reserve(std::distance(sit, send));

            if (sit == send)
            {
                // all elements are on the same partition
                local_iterator_type beg = traits::local(first);
                local_iterator_type end = traits::local(last);
                if (beg != end)
                {
                    segments.push_back(
                        hpx::make_future<SegIter>(
                            dispatch_async(traits::get_id(sit), algo,
                                policy, forced_seq(), beg, end, f, proj),
                            [send](local_iterator_type const& out)
                                -> SegIter
                            {
                                return traits::compose(send, out);
                            }));
                }
            }
            else {
                // handle the remaining part of the first partition
                local_iterator_type beg = traits::local(first);
                local_iterator_type end = traits::end(sit);
                if (beg != end)
                {
                    segments.push_back(
                        hpx::make_future<SegIter>(
                            dispatch_async(traits::get_id(sit), algo,
                                policy, forced_seq(), beg, end, f, proj),
                            [sit](local_iterator_type const& out)
                                -> SegIter
                            {
                                return traits::compose(sit, out);
                            }));
                }

                // handle all of the full partitions
                for (++sit; sit != send; ++sit)
                {
                    beg = traits::begin(sit);
                    end = traits::end(sit);
                    if (beg != end)
                    {
                        segments.push_back(
                            hpx::make_future<SegIter>(
                                dispatch_async(traits::get_id(sit), algo,
                                    policy, forced_seq(), beg, end, f, proj),
                                [sit](local_iterator_type const& out)
                                    -> SegIter
                                {
                                    return traits::compose(sit, out);
                                }));
                    }
                }

                // handle the beginning of the last partition
                beg = traits::begin(sit);
                end = traits::local(last);
                if (beg != end)
                {
                    segments.push_back(
                        hpx::make_future<SegIter>(
                            dispatch_async(traits::get_id(sit), algo,
                                policy, forced_seq(), beg, end, f, proj),
                            [sit](local_iterator_type const& out)
                                -> SegIter
                            {
                                return traits::compose(sit, out);
                            }));
                }
            }

            return result::get(
                dataflow(
                    [=](std::vector<hpx::future<SegIter> > && r)
                        ->  SegIter
                    {
                        // handle any remote exceptions, will throw on error
                        std::list<boost::exception_ptr> errors;
                        parallel::util::detail::handle_remote_exceptions<
                            ExPolicy
                        >::call(r, errors);

                        std::vector<SegIter> res =
                            hpx::util::unwrapped(std::move(r));
                        return Algo::sequential_minmax_element_ind(
                            policy, res.begin(), res.size(), f, proj);
                    },
                    std::move(segments)));
        }
Ejemplo n.º 7
0
        static typename util::detail::algorithm_result<ExPolicy, T>::type
        segmented_transform_reduce(Algo && algo, ExPolicy const& policy,
            SegIter first, SegIter last, T && init,
            Reduce && red_op, Convert && conv_op, std::false_type)
        {
            typedef hpx::traits::segmented_iterator_traits<SegIter> traits;
            typedef typename traits::segment_iterator segment_iterator;
            typedef typename traits::local_iterator local_iterator_type;
            typedef util::detail::algorithm_result<ExPolicy, T> result;

            typedef std::integral_constant<bool,
                    !hpx::traits::is_forward_iterator<SegIter>::value
                > forced_seq;

            segment_iterator sit = traits::segment(first);
            segment_iterator send = traits::segment(last);

            std::vector<shared_future<T> > segments;
            segments.reserve(std::distance(sit, send));

            if (sit == send)
            {
                // all elements are on the same partition
                local_iterator_type beg = traits::local(first);
                local_iterator_type end = traits::local(last);
                if (beg != end)
                {
                    segments.push_back(
                        dispatch_async(traits::get_id(sit),
                            algo, policy, forced_seq(),
                            beg, end, init, red_op, conv_op)
                    );
                }
            }
            else {
                // handle the remaining part of the first partition
                local_iterator_type beg = traits::local(first);
                local_iterator_type end = traits::end(sit);
                if (beg != end)
                {
                    segments.push_back(
                        dispatch_async(traits::get_id(sit),
                            algo, policy, forced_seq(),
                            beg, end, init, red_op, conv_op)
                    );
                }

                // handle all of the full partitions
                for (++sit; sit != send; ++sit)
                {
                    beg = traits::begin(sit);
                    end = traits::end(sit);
                    if (beg != end)
                    {
                        segments.push_back(
                            dispatch_async(traits::get_id(sit),
                                algo, policy, forced_seq(),
                                beg, end, init, red_op, conv_op)
                        );
                    }
                }

                // handle the beginning of the last partition
                beg = traits::begin(sit);
                end = traits::local(last);
                if (beg != end)
                {
                    segments.push_back(
                        dispatch_async(traits::get_id(sit),
                            algo, policy, forced_seq(),
                            beg, end, init, red_op, conv_op)
                    );
                }
            }

            return result::get(
                dataflow(
                    [=](std::vector<shared_future<T> > && r) -> T
                    {
                        // handle any remote exceptions, will throw on error
                        std::list<boost::exception_ptr> errors;
                        parallel::util::detail::handle_remote_exceptions<
                            ExPolicy
                        >::call(r, errors);

                        // VS2015RC bails out if red_op is capture by ref
                        return std::accumulate(
                            r.begin(), r.end(), init,
                            [=](T const& val, shared_future<T>& curr)
                            {
                                return red_op(val, curr.get());
                            });
                    },
                    std::move(segments)));
        }
Ejemplo n.º 8
0
        static typename util::detail::algorithm_result<
            ExPolicy, typename std::iterator_traits<SegIter>::difference_type
        >::type
        segmented_count(Algo && algo, ExPolicy const& policy,
            SegIter first, SegIter last, T const& value, std::false_type)
        {
            typedef hpx::traits::segmented_iterator_traits<SegIter> traits;
            typedef typename traits::segment_iterator segment_iterator;
            typedef typename traits::local_iterator local_iterator_type;

            typedef std::integral_constant<bool,
                    !hpx::traits::is_forward_iterator<SegIter>::value
                > forced_seq;

            typedef typename std::iterator_traits<SegIter>::difference_type
                value_type;
            typedef util::detail::algorithm_result<ExPolicy, value_type> result;

            segment_iterator sit = traits::segment(first);
            segment_iterator send = traits::segment(last);

            std::vector<shared_future<value_type> > segments;
            segments.reserve(std::distance(sit, send));

            if (sit == send)
            {
                // all elements are on the same partition
                local_iterator_type beg = traits::local(first);
                local_iterator_type end = traits::local(last);
                if (beg != end)
                {
                    segments.push_back(dispatch_async(traits::get_id(sit),
                        algo, policy, forced_seq(), beg, end, value));
                }
            }
            else {
                // handle the remaining part of the first partition
                local_iterator_type beg = traits::local(first);
                local_iterator_type end = traits::end(sit);
                if (beg != end)
                {
                    segments.push_back(dispatch_async(traits::get_id(sit),
                        algo, policy, forced_seq(), beg, end, value));
                }

                // handle all of the full partitions
                for (++sit; sit != send; ++sit)
                {
                    beg = traits::begin(sit);
                    end = traits::end(sit);
                    if (beg != end)
                    {
                        segments.push_back(dispatch_async(traits::get_id(sit),
                            algo, policy, forced_seq(), beg, end, value));
                    }
                }

                // handle the beginning of the last partition
                beg = traits::begin(sit);
                end = traits::local(last);
                if (beg != end)
                {
                    segments.push_back(dispatch_async(traits::get_id(sit),
                        algo, policy, forced_seq(), beg, end, value));
                }
            }

            return result::get(
                dataflow(
                    hpx::util::unwrapped([=](std::vector<value_type> && r)
                    {
                        return std::accumulate(r.begin(), r.end(), value_type());
                    }),
                    segments));
        }
Ejemplo n.º 9
0
void TypeAnalyzer::analyze(const BinaryOperator *binary) {
    /* Be careful: these pointers become kinda invalid after doing unionSet(). */
    Type *type = types().getType(binary);
    Type *leftType = types().getType(binary->left());
    Type *rightType = types().getType(binary->right());

    const dflow::Value *value = dataflow().getValue(binary->left());
    const dflow::Value *leftValue = dataflow().getValue(binary->left());
    const dflow::Value *rightValue = dataflow().getValue(binary->right());

    switch (binary->operatorKind()) {
    case BinaryOperator::ADD:
        if (leftType->isInteger() && rightType->isInteger()) {
            type->makeInteger();
        }
        if ((leftType->isInteger() && rightType->isPointer()) ||
                (leftType->isPointer() && rightType->isInteger())) {
            type->makePointer();
        }
        if (type->isInteger()) {
            leftType->makeInteger();
            rightType->makeInteger();
        }
        if (type->isPointer()) {
            if (leftType->isInteger()) {
                rightType->makePointer();
            }
            if (rightType->isInteger()) {
                leftType->makePointer();
            }
            if (leftType->isPointer()) {
                rightType->makeInteger();
            }
            if (rightType->isPointer()) {
                leftType->makeInteger();
            }
            if (!leftType->isPointer() && !rightType->isPointer()) {
                if (leftValue->isMultiplication()) {
                    rightType->makePointer();
                } else if (rightValue->isMultiplication()) {
                    leftType->makePointer();
                } else if (leftValue->isConstant()) {
                    if (leftValue->constantValue().value() < 4096) {
                        leftType->makeInteger();
                    } else {
                        leftType->makePointer();
                    }
                } else if (rightValue->isConstant()) {
                    if (rightValue->constantValue().value() < 4096) {
                        rightType->makeInteger();
                    } else {
                        rightType->makePointer();
                    }
                }
            }
        }

        if (leftType->isUnsigned() || rightType->isUnsigned()) {
            type->makeUnsigned();
        }
        if (leftType->isSigned() && rightType->isSigned()) {
            type->makeSigned();
        }
        if (type->isSigned()) {
            leftType->makeSigned();
            rightType->makeSigned();
        }
        if (type->isUnsigned()) {
            if (leftType->isSigned()) {
                rightType->makeUnsigned();
            }
            if (rightType->isSigned()) {
                rightType->makeUnsigned();
            }
        }

        if (rightValue->isConstant()) {
            if (type == leftType) {
                type->updateFactor(rightValue->constantValue().absoluteValue());
            } else {
#ifdef NC_STRUCT_RECOVERY
                if (!value->isStackOffset()) {
                    leftType->addOffset(rightValue->constantValue().signedValue(), type);
                }
#endif
            }
        }
        if (leftValue->isConstant()) {
            if (type == rightType) {
                type->updateFactor(leftValue->constantValue().absoluteValue());
            } else {
#ifdef NC_STRUCT_RECOVERY
                if (!value->isStackOffset()) {
                    rightType->addOffset(leftValue->constantValue().signedValue(), type);
                }
#endif
            }
        }

        if (leftType->isPointer() && rightValue->isMultiplication()) {
            type->makePointer(leftType->pointee());
        }
        if (rightType->isPointer() && leftValue->isMultiplication()) {
            type->makePointer(rightType->pointee());
        }
        break;

    case BinaryOperator::SUB:
        if (leftType->isInteger() && rightType->isInteger()) {
            type->makeInteger();
        }
        if (leftType->isPointer() && rightType->isInteger()) {
            type->makePointer();
        }
        if (type->isPointer()) {
            leftType->makePointer();
            rightType->makeInteger();
        }

        if (leftType->isUnsigned() || rightType->isUnsigned()) {
            type->makeUnsigned();
        }
        if (leftType->isSigned() && rightType->isSigned()) {
            type->makeSigned();
        }
        if (type->isSigned()) {
            leftType->makeSigned();
            rightType->makeSigned();
        }
        if (type->isUnsigned()) {
            if (leftType->isSigned()) {
                rightType->makeUnsigned();
            }
            if (rightType->isSigned()) {
                rightType->makeUnsigned();
            }
        }

        if (rightValue->isConstant()) {
            if (type == leftType) {
                type->updateFactor(rightValue->constantValue().absoluteValue());
            } else {
#ifdef NC_STRUCT_RECOVERY
                if (!value->isStackOffset()) {
                    leftType->addOffset(-rightValue->constantValue().signedValue(), type);
                }
#endif
            }
        }

        if (leftType->isPointer() && rightValue->isMultiplication()) {
            type->makePointer(leftType->pointee());
        }
        break;

    case BinaryOperator::MUL:
        type->makeInteger();
        leftType->makeInteger();
        rightType->makeInteger();

        if (leftType->isUnsigned() || rightType->isUnsigned()) {
            type->makeUnsigned();
        }
        if (leftType->isSigned() && rightType->isSigned()) {
            type->makeSigned();
        }
        if (type->isSigned()) {
            leftType->makeSigned();
            rightType->makeSigned();
        }
        if (type->isUnsigned()) {
            if (leftType->isSigned()) {
                rightType->makeUnsigned();
            }
            if (rightType->isSigned()) {
                rightType->makeUnsigned();
            }
        }

        if (rightValue->isConstant()) {
            type->updateFactor(leftType->factor() * rightValue->constantValue().value());
        }
        if (leftValue->isConstant()) {
            type->updateFactor(rightType->factor() * leftValue->constantValue().value());
        }
        break;

    case BinaryOperator::SIGNED_DIV:
        leftType->makeInteger();
        rightType->makeInteger();
        type->makeInteger();

        leftType->makeSigned();
        rightType->makeSigned();
        type->makeSigned();
        break;

    case BinaryOperator::UNSIGNED_DIV:
        type->makeInteger();
        leftType->makeInteger();
        rightType->makeInteger();

        if (leftType->isSigned()) {
            rightType->makeUnsigned();
        }
        if (rightType->isUnsigned()) {
            leftType->makeSigned();
        }
        type->makeUnsigned();
        break;

    case BinaryOperator::SIGNED_REM:
        leftType->makeInteger();
        rightType->makeInteger();
        type->makeInteger();

        leftType->makeSigned();
        rightType->makeSigned();
        type->makeSigned();
        break;

    case BinaryOperator::UNSIGNED_REM:
        type->makeInteger();
        leftType->makeInteger();
        rightType->makeInteger();

        if (leftType->isSigned()) {
            rightType->makeUnsigned();
        }
        if (rightType->isUnsigned()) {
            leftType->makeSigned();
        }
        type->makeUnsigned();
        break;

    case BinaryOperator::BITWISE_AND: /* FALLTHROUGH */
    case BinaryOperator::LOGICAL_AND: /* FALLTHROUGH */
    case BinaryOperator::BITWISE_OR: /* FALLTHROUGH */
    case BinaryOperator::LOGICAL_OR: /* FALLTHROUGH */
    case BinaryOperator::BITWISE_XOR:
        leftType->makeInteger();
        rightType->makeInteger();
        type->makeInteger();

        leftType->makeUnsigned();
        rightType->makeUnsigned();
        type->makeUnsigned();
        break;

    case BinaryOperator::SHL:
        leftType->makeInteger();
        rightType->makeInteger();
        type->makeInteger();

        rightType->makeUnsigned();
        if (leftType->isSigned()) {
            type->makeSigned();
        }
        if (leftType->isUnsigned()) {
            type->makeUnsigned();
        }
        if (type->isSigned()) {
            leftType->makeSigned();
        }
        if (type->isUnsigned()) {
            leftType->makeUnsigned();
        }

        if (rightValue->isConstant()) {
            type->updateFactor(leftType->factor() * (ConstantValue(1) << rightValue->constantValue().value()));
        }
        break;

    case BinaryOperator::SHR:
        leftType->makeInteger();
        rightType->makeInteger();
        type->makeInteger();

        leftType->makeUnsigned();
        type->makeUnsigned();
        break;

    case BinaryOperator::SAR:
        leftType->makeInteger();
        rightType->makeInteger();
        type->makeInteger();

        leftType->makeSigned();
        type->makeSigned();
        break;

    case BinaryOperator::EQUAL:
        leftType->unionSet(rightType);
        break;

    case BinaryOperator::SIGNED_LESS: /* FALLTHROUGH */
    case BinaryOperator::SIGNED_LESS_OR_EQUAL: /* FALLTHROUGH */
    case BinaryOperator::SIGNED_GREATER: /* FALLTHROUGH */
    case BinaryOperator::SIGNED_GREATER_OR_EQUAL:
        leftType->makeSigned();
        rightType->makeSigned();
        leftType->unionSet(rightType);
        break;

    case BinaryOperator::UNSIGNED_LESS: /* FALLTHROUGH */
    case BinaryOperator::UNSIGNED_LESS_OR_EQUAL: /* FALLTHROUGH */
    case BinaryOperator::UNSIGNED_GREATER: /* FALLTHROUGH */
    case BinaryOperator::UNSIGNED_GREATER_OR_EQUAL:
        if (rightType->isSigned()) {
            leftType->makeUnsigned();
        } else if (leftType->isSigned()) {
            rightType->makeUnsigned();
        } else {
            leftType->makeUnsigned();
            rightType->makeUnsigned();
        }
        leftType->unionSet(rightType);
        break;

    default:
        unreachable();
        break;
    }
}
Ejemplo n.º 10
0
void DataflowAnalyzer::analyze(const CFG &cfg) {
    /*
     * Returns true if the given term does not cover given memory location.
     */
    auto notCovered = [this](const MemoryLocation &mloc, const Term *term) -> bool {
        return !dataflow().getMemoryLocation(term).covers(mloc);
    };

    /* Mapping of a basic block to the definitions reaching its end. */
    boost::unordered_map<const BasicBlock *, ReachingDefinitions> outDefinitions;

    /*
     * Running abstract interpretation until reaching a fixpoint several times in a row.
     */
    int niterations = 0;
    int nfixpoints = 0;

    while (nfixpoints++ < 3) {
        /*
         * Run abstract interpretation on all basic blocks.
         */
        foreach (auto basicBlock, cfg.basicBlocks()) {
            ReachingDefinitions definitions;

            /* Merge reaching definitions from predecessors. */
            foreach (const BasicBlock *predecessor, cfg.getPredecessors(basicBlock)) {
                definitions.merge(outDefinitions[predecessor]);
            }

            /* Remove definitions that do not cover the memory location that they define. */
            definitions.filterOut(notCovered);

            /* Execute all the statements in the basic block. */
            foreach (auto statement, basicBlock->statements()) {
                execute(statement, definitions);
            }

            /* Something has changed? */
            ReachingDefinitions &oldDefinitions(outDefinitions[basicBlock]);
            if (oldDefinitions != definitions) {
                oldDefinitions = std::move(definitions);
                nfixpoints = 0;
            }
        }

        /*
         * Some terms might have changed their addresses. Filter again.
         */
        foreach (auto &termAndDefinitions, dataflow().term2definitions()) {
            termAndDefinitions.second.filterOut(notCovered);
        }

        /*
         * Do we loop infinitely?
         */
        if (++niterations >= 30) {
            log_.warning(tr("%1: Fixpoint was not reached after %2 iterations.").arg(Q_FUNC_INFO).arg(niterations));
            break;
        }

        canceled_.poll();
    }

    /*
     * Remove information about terms that disappeared.
     * Terms can disappear if e.g. a call is deinstrumented during the analysis.
     */
    auto disappeared = [](const Term *term){ return term->statement()->basicBlock() == nullptr; };

    std::vector<const Term *> disappearedTerms;
    foreach (auto &termAndDefinitions, dataflow().term2definitions()) {
        termAndDefinitions.second.filterOut([disappeared](const MemoryLocation &, const Term *term) { return disappeared(term); } );
    }

    remove_if(dataflow().term2value(), disappeared);
    remove_if(dataflow().term2location(), disappeared);
    remove_if(dataflow().term2definitions(), disappeared);
}
Ejemplo n.º 11
0
Value *DataflowAnalyzer::computeValue(const Term *term, const MemoryLocation &memoryLocation,
                                      const ReachingDefinitions &definitions) {
    assert(term);
    assert(term->isRead());
    assert(memoryLocation || definitions.empty());

    auto value = dataflow().getValue(term);

    if (definitions.empty()) {
        return value;
    }

    auto byteOrder = architecture()->getByteOrder(memoryLocation.domain());

    /*
     * Merge abstract values.
     */
    auto abstractValue = value->abstractValue();

    foreach (const auto &chunk, definitions.chunks()) {
        assert(memoryLocation.covers(chunk.location()));

        /*
         * Mask of bits inside abstractValue which are covered by chunk's location.
         */
        auto mask = bitMask<ConstantValue>(chunk.location().size());
        if (byteOrder == ByteOrder::LittleEndian) {
            mask = bitShift(mask, chunk.location().addr() - memoryLocation.addr());
        } else {
            mask = bitShift(mask, memoryLocation.endAddr() - chunk.location().endAddr());
        }

        foreach (auto definition, chunk.definitions()) {
            auto definitionLocation = dataflow().getMemoryLocation(definition);
            assert(definitionLocation.covers(chunk.location()));

            auto definitionValue = dataflow().getValue(definition);
            auto definitionAbstractValue = definitionValue->abstractValue();

            /*
             * Shift definition's abstract value to match term's location.
             */
            if (byteOrder == ByteOrder::LittleEndian) {
                definitionAbstractValue.shift(definitionLocation.addr() - memoryLocation.addr());
            } else {
                definitionAbstractValue.shift(memoryLocation.endAddr() - definitionLocation.endAddr());
            }

            /* Project the value to the defined location. */
            definitionAbstractValue.project(mask);

            /* Update term's value. */
            abstractValue.merge(definitionAbstractValue);
        }
    }

    value->setAbstractValue(abstractValue.resize(term->size()));

    /*
     * Merge stack offset and product flags.
     *
     * Heuristic: merge information only from terms that define lower bits of the term's value.
     */
    const std::vector<const Term *> *lowerBitsDefinitions = nullptr;

    if (byteOrder == ByteOrder::LittleEndian) {
        if (definitions.chunks().front().location().addr() == memoryLocation.addr()) {
            lowerBitsDefinitions = &definitions.chunks().front().definitions();
        }
    } else {
        if (definitions.chunks().back().location().endAddr() == memoryLocation.endAddr()) {
            lowerBitsDefinitions = &definitions.chunks().back().definitions();
        }
    }

    if (lowerBitsDefinitions) {
        foreach (auto definition, *lowerBitsDefinitions) {
            auto definitionValue = dataflow().getValue(definition);

            if (definitionValue->isNotStackOffset()) {
                value->makeNotStackOffset();
            } else if (definitionValue->isStackOffset()) {
                value->makeStackOffset(definitionValue->stackOffset());
            }

            if (definitionValue->isNotProduct()) {
                value->makeNotProduct();
            } else if (definitionValue->isProduct()) {
                value->makeProduct();
            }
        }
    }

    /*
     * Merge return address flag.
     */
    if (definitions.chunks().front().location() == memoryLocation) {
        foreach (auto definition, definitions.chunks().front().definitions()) {
            auto definitionValue = dataflow().getValue(definition);
            if (definitionValue->isNotReturnAddress()) {
                value->makeNotReturnAddress();
            } else if (definitionValue->isReturnAddress()) {
                value->makeReturnAddress();
            }
        }
    }
Ejemplo n.º 12
0
Value *DataflowAnalyzer::computeValue(const Term *term, const ReachingDefinitions &definitions) {
    switch (term->kind()) {
        case Term::INT_CONST: {
            auto constant = term->asConstant();
            Value *value = dataflow().getValue(constant);
            value->setAbstractValue(constant->value());
            value->makeNotStackOffset();
            value->makeNotProduct();
            value->makeNotReturnAddress();
            return value;
        }
        case Term::INTRINSIC: {
            auto intrinsic = term->asIntrinsic();
            Value *value = dataflow().getValue(intrinsic);

            switch (intrinsic->intrinsicKind()) {
                case Intrinsic::UNKNOWN: /* FALLTHROUGH */
                case Intrinsic::UNDEFINED: {
                    value->setAbstractValue(AbstractValue(term->size(), -1, -1));
                    value->makeNotStackOffset();
                    value->makeNotProduct();
                    value->makeNotReturnAddress();
                    break;
                }
                case Intrinsic::ZERO_STACK_OFFSET: {
                    value->setAbstractValue(AbstractValue(term->size(), -1, -1));
                    value->makeStackOffset(0);
                    value->makeNotProduct();
                    value->makeNotReturnAddress();
                    break;
                }
                case Intrinsic::RETURN_ADDRESS: {
                    value->setAbstractValue(AbstractValue(term->size(), -1, -1));
                    value->makeNotStackOffset();
                    value->makeNotProduct();
                    value->makeReturnAddress();
                    break;
                }
                default: {
                    log_.warning(tr("%1: Unknown kind of intrinsic: %2.").arg(Q_FUNC_INFO).arg(intrinsic->intrinsicKind()));
                    break;
                }
            }
            return value;
        }
        case Term::MEMORY_LOCATION_ACCESS: /* FALLTHROUGH */
        case Term::DEREFERENCE: {
            const auto &memoryLocation = computeMemoryLocation(term, definitions);
            const auto &reachingDefinitions = computeReachingDefinitions(term, memoryLocation, definitions);
            return computeValue(term, memoryLocation, reachingDefinitions);
        }
        case Term::UNARY_OPERATOR:
            return computeValue(term->asUnaryOperator(), definitions);
        case Term::BINARY_OPERATOR:
            return computeValue(term->asBinaryOperator(), definitions);
        case Term::CHOICE: {
            auto choice = term->asChoice();
            auto value = dataflow().getValue(choice);
            auto preferredValue = computeValue(choice->preferredTerm(), definitions);
            auto defaultValue = computeValue(choice->defaultTerm(), definitions);

            if (!dataflow().getDefinitions(choice->preferredTerm()).empty()) {
                *value = *preferredValue;
            } else {
                *value = *defaultValue;
            }

            return value;
        }
        default: {
            log_.warning(tr("%1: Unknown term kind: %2.").arg(Q_FUNC_INFO).arg(term->kind()));
            return dataflow().getValue(term);
        }
    }
}
Ejemplo n.º 13
0
Archivo: main.c Proyecto: zayac/eq
int
main (int argc, char *argv[])
{
  int c, ret = 0;
  char *subopts;
  char *value;
  char *src_name = NULL;
  extern char *optarg;
  extern int optind;

  struct eq_lexer *lex = (struct eq_lexer *) malloc (sizeof (struct eq_lexer));
  struct eq_parser *parser = (struct eq_parser *) malloc (sizeof (struct eq_parser));

  init_global ();
  init_global_tree ();
  init_options ();

  progname = strrchr (argv[0], '/');
  if (NULL == progname)
    progname = argv[0];
  else
    progname++;

  while (-1 != (c = getopt (argc, argv, "B:P:V")))
    switch (c)
      {
      case 'P':
	subopts = optarg;
	while (*subopts != '\0')
	  switch (getsubopt (&subopts, p_opts, &value))
	    {
	    case OPT_PRINT_PROGRAM:
	      options.print_program = true;
	      break;
	    case OPT_PRINT_MATCHES:
	      options.print_matches = true;
	      break;
	    case OPT_PRINT_TYPES:
	      options.print_types = true;
	      break;
	    default:
	      fprintf (stderr, "unknown -P suboption `%s'\n", value);
	      goto cleanup;
	      break;
	    }
	break;
      case 'B':
	subopts = optarg;
	while (*subopts != '\0')
	  switch (getsubopt (&subopts, b_opts, &value))
	    {
	    case OPT_BREAK_PARSER:
	      options.break_option = break_parser;
	      break;
	    case OPT_BREAK_TYPECHECK:
	      options.break_option = break_typecheck;
	      break;
	    case OPT_BREAK_CONTROLFLOW:
	      options.break_option = break_controlflow;
	    case OPT_BREAK_DATAFLOW:
	      options.break_option = break_dataflow;
	      break;
	    default:
	      fprintf (stderr, "unknown -B suboption `%s'\n", value);
	      goto cleanup;
	      break;
	    }
	break;
      case 'V':
	version ();
	goto cleanup;
      default:
	usage ();
	goto cleanup;
      }

  if (options.print_types
      && !(options.print_program || options.print_matches))
    fprintf (stderr, "warning: 'types' flag is useless without either "
	     "'program' flag or 'matches' flag\n");

  argv += optind;

  /* FIXME: What if we have multiple files?  */
  if (NULL == *argv)
    {
      fprintf (stderr, "%s:error: filename argument required\n", progname);
      usage ();
      ret = -1;
      goto cleanup;
    }

  /* Initialize the lexer.  */
  if (!eq_lexer_init (lex, *argv))
    {
      fprintf (stderr, "%s cannot create a lexer for file `%s'\n", progname,
	       *argv);
      ret = -2;
      goto cleanup;
    }
  else
    {
      /* Discard extension from file to compile.  */
      char* start = strrchr (*argv, '/');
      char* ext = strrchr (*argv, '.');
      int size = 0;
      
      if (start == NULL)
	start = *argv;
      else
	start += 1;
      if (ext == NULL)
	size = strlen(start);
      else
	size = ext - start;
      src_name = strndup (start, size);
    }


  /* Initialize the parser.  */
  eq_parser_init (parser, lex);

  if ((ret += eq_parse (parser)) == 0 && options.break_option != break_parser)
    ret += typecheck ();

  /* printing debug routine.  */
  if (options.print_program)
    {
      xfile *  xf = xfile_init_file_stdout ();

      printf ("\n######### Output ########\n");

      print_program (xf);

      xfile_finalize (xf);
    }

  if (options.print_matches)
    {
      printf ("\n####### Transforms ########\n");
      print_matches ();
    }
 
  if (options.break_option != break_typecheck
   && options.break_option != break_parser && !ret)
    controlflow ();

  if (options.break_option != break_controlflow
   && options.break_option != break_typecheck
   && options.break_option != break_parser && !ret)
    dataflow ();

  if (options.break_option != break_dataflow
   && options.break_option != break_controlflow
   && options.break_option != break_typecheck
   && options.break_option != break_parser && !ret)
    codegen (src_name);
  printf ("note: finished compiling.\n");

  free (src_name);
cleanup:
  eq_parser_finalize (parser);
  finalize_global_tree ();
  finalize_global ();

  /* That should be called at the very end.  */
  free_atomic_trees ();

  if (parser)
    free (parser);
  if (lex)
    free (lex);

  return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}