<commit_before>/*
 * Copyright (C) 2015-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <experimental/source_location>

#include <boost/range/irange.hpp>
#include <boost/range/adaptor/uniqued.hpp>

#include <seastar/core/thread.hh>

#include <seastar/testing/test_case.hh>
#include <seastar/testing/thread_test_case.hh>
#include "test/lib/test_services.hh"
#include "test/lib/mutation_source_test.hh"
#include "test/lib/cql_test_env.hh"
#include "test/lib/dummy_sharder.hh"
#include "test/lib/reader_lifecycle_policy.hh"
#include "test/lib/log.hh"

#include "dht/sharder.hh"
#include "mutation_reader.hh"
#include "schema_registry.hh"
#include "service/priority_manager.hh"

// Best run with SMP >= 2
SEASTAR_THREAD_TEST_CASE(test_multishard_combining_reader_as_mutation_source) {
    if (smp::count < 2) {
        std::cerr << "Cannot run test " << get_name() << " with smp::count < 2" << std::endl;
        return;
    }

    // It has to be a container that does not invalidate pointers
    std::list<dummy_sharder> keep_alive_sharder;

    do_with_cql_env_thread([&] (cql_test_env& env) -> future<> {
        auto make_populate = [&] (bool evict_paused_readers, bool single_fragment_buffer) {
            return [&, evict_paused_readers, single_fragment_buffer] (schema_ptr s, const std::vector<mutation>& mutations) mutable {
                // We need to group mutations that have the same token so they land on the same shard.
                std::map<dht::token, std::vector<frozen_mutation>> mutations_by_token;

                for (const auto& mut : mutations) {
                    mutations_by_token[mut.token()].push_back(freeze(mut));
                }

                dummy_sharder sharder(s->get_sharder(), mutations_by_token);

                auto merged_mutations = boost::copy_range<std::vector<std::vector<frozen_mutation>>>(mutations_by_token | boost::adaptors::map_values);

                auto remote_memtables = make_lw_shared<std::vector<foreign_ptr<lw_shared_ptr<memtable>>>>();
                for (unsigned shard = 0; shard < sharder.shard_count(); ++shard) {
                    auto remote_mt = smp::submit_to(shard, [shard, gs = global_schema_ptr(s), &merged_mutations, sharder] {
                        auto s = gs.get();
                        auto mt = make_lw_shared<memtable>(s);

                        for (unsigned i = shard; i < merged_mutations.size(); i += sharder.shard_count()) {
                            for (auto& mut : merged_mutations[i]) {
                                mt->apply(mut.unfreeze(s));
                            }
                        }

                        return make_foreign(mt);
                    }).get0();
                    remote_memtables->emplace_back(std::move(remote_mt));
                }
                keep_alive_sharder.push_back(sharder);

                return mutation_source([&, remote_memtables, evict_paused_readers, single_fragment_buffer] (schema_ptr s,
                        reader_permit permit,
                        const dht::partition_range& range,
                        const query::partition_slice& slice,
                        const io_priority_class& pc,
                        tracing::trace_state_ptr trace_state,
                        streamed_mutation::forwarding fwd_sm,
                        mutation_reader::forwarding fwd_mr) mutable {
                    auto factory = [remote_memtables, single_fragment_buffer] (
                            schema_ptr s,
                            reader_permit permit,
                            const dht::partition_range& range,
                            const query::partition_slice& slice,
                            const io_priority_class& pc,
                            tracing::trace_state_ptr trace_state,
                            mutation_reader::forwarding fwd_mr) {
                            auto reader = remote_memtables->at(this_shard_id())->make_flat_reader(s, std::move(permit), range, slice, pc, std::move(trace_state),
                                    streamed_mutation::forwarding::no, fwd_mr);
                            if (single_fragment_buffer) {
                                reader.set_max_buffer_size(1);
                            }
                            return reader;
                    };

                    auto lifecycle_policy = seastar::make_shared<test_reader_lifecycle_policy>(std::move(factory), evict_paused_readers);
                    auto mr = make_multishard_combining_reader_for_tests(keep_alive_sharder.back(), std::move(lifecycle_policy), s,
                            std::move(permit), range, slice, pc, trace_state, fwd_mr);
                    if (fwd_sm == streamed_mutation::forwarding::yes) {
                        return make_forwardable(std::move(mr));
                    }
                    return mr;
                });
            };
        };

        testlog.info("run_mutation_source_tests(evict_readers=false, single_fragment_buffer=false)");
        run_mutation_source_tests(make_populate(false, false));

        testlog.info("run_mutation_source_tests(evict_readers=true, single_fragment_buffer=false)");
        run_mutation_source_tests(make_populate(true, false));

        testlog.info("run_mutation_source_tests(evict_readers=true, single_fragment_buffer=true)");
        run_mutation_source_tests(make_populate(true, true));

        return make_ready_future<>();
    }).get();
}
<commit_msg>test: Move out internals of test_multishard_combining_reader_as_mutation_source<commit_after>/*
 * Copyright (C) 2015-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <experimental/source_location>

#include <boost/range/irange.hpp>
#include <boost/range/adaptor/uniqued.hpp>

#include <seastar/core/thread.hh>

#include <seastar/testing/test_case.hh>
#include <seastar/testing/thread_test_case.hh>
#include "test/lib/test_services.hh"
#include "test/lib/mutation_source_test.hh"
#include "test/lib/cql_test_env.hh"
#include "test/lib/dummy_sharder.hh"
#include "test/lib/reader_lifecycle_policy.hh"
#include "test/lib/log.hh"

#include "dht/sharder.hh"
#include "mutation_reader.hh"
#include "schema_registry.hh"
#include "service/priority_manager.hh"

// It has to be a container that does not invalidate pointers
static std::list<dummy_sharder> keep_alive_sharder;

static auto make_populate(bool evict_paused_readers, bool single_fragment_buffer) {
            return [&, evict_paused_readers, single_fragment_buffer] (schema_ptr s, const std::vector<mutation>& mutations) mutable {
                // We need to group mutations that have the same token so they land on the same shard.
                std::map<dht::token, std::vector<frozen_mutation>> mutations_by_token;

                for (const auto& mut : mutations) {
                    mutations_by_token[mut.token()].push_back(freeze(mut));
                }

                dummy_sharder sharder(s->get_sharder(), mutations_by_token);

                auto merged_mutations = boost::copy_range<std::vector<std::vector<frozen_mutation>>>(mutations_by_token | boost::adaptors::map_values);

                auto remote_memtables = make_lw_shared<std::vector<foreign_ptr<lw_shared_ptr<memtable>>>>();
                for (unsigned shard = 0; shard < sharder.shard_count(); ++shard) {
                    auto remote_mt = smp::submit_to(shard, [shard, gs = global_schema_ptr(s), &merged_mutations, sharder] {
                        auto s = gs.get();
                        auto mt = make_lw_shared<memtable>(s);

                        for (unsigned i = shard; i < merged_mutations.size(); i += sharder.shard_count()) {
                            for (auto& mut : merged_mutations[i]) {
                                mt->apply(mut.unfreeze(s));
                            }
                        }

                        return make_foreign(mt);
                    }).get0();
                    remote_memtables->emplace_back(std::move(remote_mt));
                }
                keep_alive_sharder.push_back(sharder);

                return mutation_source([&, remote_memtables, evict_paused_readers, single_fragment_buffer] (schema_ptr s,
                        reader_permit permit,
                        const dht::partition_range& range,
                        const query::partition_slice& slice,
                        const io_priority_class& pc,
                        tracing::trace_state_ptr trace_state,
                        streamed_mutation::forwarding fwd_sm,
                        mutation_reader::forwarding fwd_mr) mutable {
                    auto factory = [remote_memtables, single_fragment_buffer] (
                            schema_ptr s,
                            reader_permit permit,
                            const dht::partition_range& range,
                            const query::partition_slice& slice,
                            const io_priority_class& pc,
                            tracing::trace_state_ptr trace_state,
                            mutation_reader::forwarding fwd_mr) {
                            auto reader = remote_memtables->at(this_shard_id())->make_flat_reader(s, std::move(permit), range, slice, pc, std::move(trace_state),
                                    streamed_mutation::forwarding::no, fwd_mr);
                            if (single_fragment_buffer) {
                                reader.set_max_buffer_size(1);
                            }
                            return reader;
                    };

                    auto lifecycle_policy = seastar::make_shared<test_reader_lifecycle_policy>(std::move(factory), evict_paused_readers);
                    auto mr = make_multishard_combining_reader_for_tests(keep_alive_sharder.back(), std::move(lifecycle_policy), s,
                            std::move(permit), range, slice, pc, trace_state, fwd_mr);
                    if (fwd_sm == streamed_mutation::forwarding::yes) {
                        return make_forwardable(std::move(mr));
                    }
                    return mr;
                });
            };
}

// Best run with SMP >= 2
SEASTAR_THREAD_TEST_CASE(test_multishard_combining_reader_as_mutation_source) {
    if (smp::count < 2) {
        std::cerr << "Cannot run test " << get_name() << " with smp::count < 2" << std::endl;
        return;
    }

    do_with_cql_env_thread([&] (cql_test_env& env) -> future<> {
        testlog.info("run_mutation_source_tests(evict_readers=false, single_fragment_buffer=false)");
        run_mutation_source_tests(make_populate(false, false));

        testlog.info("run_mutation_source_tests(evict_readers=true, single_fragment_buffer=false)");
        run_mutation_source_tests(make_populate(true, false));

        testlog.info("run_mutation_source_tests(evict_readers=true, single_fragment_buffer=true)");
        run_mutation_source_tests(make_populate(true, true));

        return make_ready_future<>();
    }).get();
}
<|endoftext|>


<commit_before>//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Dwarf emissions parts of AsmPrinter.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "asm-printer"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// Dwarf Emission Helper Routines
//===----------------------------------------------------------------------===//

/// EmitSLEB128 - emit the specified signed leb128 value.
void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
  if (isVerbose() && Desc)
    OutStreamer.AddComment(Desc);

  OutStreamer.EmitSLEB128IntValue(Value);
}

/// EmitULEB128 - emit the specified signed leb128 value.
void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc,
                             unsigned PadTo) const {
  if (isVerbose() && Desc)
    OutStreamer.AddComment(Desc);

  OutStreamer.EmitULEB128IntValue(Value, PadTo);
}

/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
void AsmPrinter::EmitCFAByte(unsigned Val) const {
  if (isVerbose()) {
    if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset + 64)
      OutStreamer.AddComment("DW_CFA_offset + Reg (" +
                             Twine(Val - dwarf::DW_CFA_offset) + ")");
    else
      OutStreamer.AddComment(dwarf::CallFrameString(Val));
  }
  OutStreamer.EmitIntValue(Val, 1);
}

static const char *DecodeDWARFEncoding(unsigned Encoding) {
  switch (Encoding) {
  case dwarf::DW_EH_PE_absptr:
    return "absptr";
  case dwarf::DW_EH_PE_omit:
    return "omit";
  case dwarf::DW_EH_PE_pcrel:
    return "pcrel";
  case dwarf::DW_EH_PE_udata4:
    return "udata4";
  case dwarf::DW_EH_PE_udata8:
    return "udata8";
  case dwarf::DW_EH_PE_sdata4:
    return "sdata4";
  case dwarf::DW_EH_PE_sdata8:
    return "sdata8";
  case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
    return "pcrel udata4";
  case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
    return "pcrel sdata4";
  case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
    return "pcrel udata8";
  case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
    return "pcrel sdata8";
  case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4
      :
    return "indirect pcrel udata4";
  case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
      :
    return "indirect pcrel sdata4";
  case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8
      :
    return "indirect pcrel udata8";
  case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8
      :
    return "indirect pcrel sdata8";
  }

  return "<unknown encoding>";
}

/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
/// encoding.  If verbose assembly output is enabled, we output comments
/// describing the encoding.  Desc is an optional string saying what the
/// encoding is specifying (e.g. "LSDA").
void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const {
  if (isVerbose()) {
    if (Desc != 0)
      OutStreamer.AddComment(Twine(Desc) + " Encoding = " +
                             Twine(DecodeDWARFEncoding(Val)));
    else
      OutStreamer.AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val));
  }

  OutStreamer.EmitIntValue(Val, 1);
}

/// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
  if (Encoding == dwarf::DW_EH_PE_omit)
    return 0;

  switch (Encoding & 0x07) {
  default:
    llvm_unreachable("Invalid encoded value.");
  case dwarf::DW_EH_PE_absptr:
    return TM.getDataLayout()->getPointerSize();
  case dwarf::DW_EH_PE_udata2:
    return 2;
  case dwarf::DW_EH_PE_udata4:
    return 4;
  case dwarf::DW_EH_PE_udata8:
    return 8;
  }
}

void AsmPrinter::EmitTTypeReference(const GlobalValue *GV,
                                    unsigned Encoding) const {
  if (GV) {
    const TargetLoweringObjectFile &TLOF = getObjFileLowering();

    const MCExpr *Exp =
        TLOF.getTTypeGlobalReference(GV, Mang, MMI, Encoding, OutStreamer);
    OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding));
  } else
    OutStreamer.EmitIntValue(0, GetSizeOfEncodedValue(Encoding));
}

/// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its
/// section.  This can be done with a special directive if the target supports
/// it (e.g. cygwin) or by emitting it as an offset from a label at the start
/// of the section.
///
/// SectionLabel is a temporary label emitted at the start of the section that
/// Label lives in.
void AsmPrinter::EmitSectionOffset(const MCSymbol *Label,
                                   const MCSymbol *SectionLabel) const {
  // On COFF targets, we have to emit the special .secrel32 directive.
  if (MAI->needsDwarfSectionOffsetDirective()) {
    OutStreamer.EmitCOFFSecRel32(Label);
    return;
  }

  // Get the section that we're referring to, based on SectionLabel.
  const MCSection &Section = SectionLabel->getSection();

  // If Label has already been emitted, verify that it is in the same section as
  // section label for sanity.
  assert((!Label->isInSection() || &Label->getSection() == &Section) &&
         "Section offset using wrong section base for label");

  // If the section in question will end up with an address of 0 anyway, we can
  // just emit an absolute reference to save a relocation.
  if (Section.isBaseAddressKnownZero()) {
    OutStreamer.EmitSymbolValue(Label, 4);
    return;
  }

  // Otherwise, emit it as a label difference from the start of the section.
  EmitLabelDifference(Label, SectionLabel, 4);
}

//===----------------------------------------------------------------------===//
// Dwarf Lowering Routines
//===----------------------------------------------------------------------===//

void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
  switch (Inst.getOperation()) {
  default:
    llvm_unreachable("Unexpected instruction");
  case MCCFIInstruction::OpDefCfaOffset:
    OutStreamer.EmitCFIDefCfaOffset(Inst.getOffset());
    break;
  case MCCFIInstruction::OpDefCfa:
    OutStreamer.EmitCFIDefCfa(Inst.getRegister(), Inst.getOffset());
    break;
  case MCCFIInstruction::OpDefCfaRegister:
    OutStreamer.EmitCFIDefCfaRegister(Inst.getRegister());
    break;
  case MCCFIInstruction::OpOffset:
    OutStreamer.EmitCFIOffset(Inst.getRegister(), Inst.getOffset());
    break;
  case MCCFIInstruction::OpRegister:
    OutStreamer.EmitCFIRegister(Inst.getRegister(), Inst.getRegister2());
    break;
  case MCCFIInstruction::OpWindowSave:
    OutStreamer.EmitCFIWindowSave();
    break;
  }
}
<commit_msg>Simplify check.<commit_after>//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Dwarf emissions parts of AsmPrinter.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "asm-printer"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// Dwarf Emission Helper Routines
//===----------------------------------------------------------------------===//

/// EmitSLEB128 - emit the specified signed leb128 value.
void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
  if (isVerbose() && Desc)
    OutStreamer.AddComment(Desc);

  OutStreamer.EmitSLEB128IntValue(Value);
}

/// EmitULEB128 - emit the specified signed leb128 value.
void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc,
                             unsigned PadTo) const {
  if (isVerbose() && Desc)
    OutStreamer.AddComment(Desc);

  OutStreamer.EmitULEB128IntValue(Value, PadTo);
}

/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
void AsmPrinter::EmitCFAByte(unsigned Val) const {
  if (isVerbose()) {
    if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset + 64)
      OutStreamer.AddComment("DW_CFA_offset + Reg (" +
                             Twine(Val - dwarf::DW_CFA_offset) + ")");
    else
      OutStreamer.AddComment(dwarf::CallFrameString(Val));
  }
  OutStreamer.EmitIntValue(Val, 1);
}

static const char *DecodeDWARFEncoding(unsigned Encoding) {
  switch (Encoding) {
  case dwarf::DW_EH_PE_absptr:
    return "absptr";
  case dwarf::DW_EH_PE_omit:
    return "omit";
  case dwarf::DW_EH_PE_pcrel:
    return "pcrel";
  case dwarf::DW_EH_PE_udata4:
    return "udata4";
  case dwarf::DW_EH_PE_udata8:
    return "udata8";
  case dwarf::DW_EH_PE_sdata4:
    return "sdata4";
  case dwarf::DW_EH_PE_sdata8:
    return "sdata8";
  case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
    return "pcrel udata4";
  case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
    return "pcrel sdata4";
  case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
    return "pcrel udata8";
  case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
    return "pcrel sdata8";
  case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4
      :
    return "indirect pcrel udata4";
  case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
      :
    return "indirect pcrel sdata4";
  case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8
      :
    return "indirect pcrel udata8";
  case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8
      :
    return "indirect pcrel sdata8";
  }

  return "<unknown encoding>";
}

/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
/// encoding.  If verbose assembly output is enabled, we output comments
/// describing the encoding.  Desc is an optional string saying what the
/// encoding is specifying (e.g. "LSDA").
void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const {
  if (isVerbose()) {
    if (Desc)
      OutStreamer.AddComment(Twine(Desc) + " Encoding = " +
                             Twine(DecodeDWARFEncoding(Val)));
    else
      OutStreamer.AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val));
  }

  OutStreamer.EmitIntValue(Val, 1);
}

/// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
  if (Encoding == dwarf::DW_EH_PE_omit)
    return 0;

  switch (Encoding & 0x07) {
  default:
    llvm_unreachable("Invalid encoded value.");
  case dwarf::DW_EH_PE_absptr:
    return TM.getDataLayout()->getPointerSize();
  case dwarf::DW_EH_PE_udata2:
    return 2;
  case dwarf::DW_EH_PE_udata4:
    return 4;
  case dwarf::DW_EH_PE_udata8:
    return 8;
  }
}

void AsmPrinter::EmitTTypeReference(const GlobalValue *GV,
                                    unsigned Encoding) const {
  if (GV) {
    const TargetLoweringObjectFile &TLOF = getObjFileLowering();

    const MCExpr *Exp =
        TLOF.getTTypeGlobalReference(GV, Mang, MMI, Encoding, OutStreamer);
    OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding));
  } else
    OutStreamer.EmitIntValue(0, GetSizeOfEncodedValue(Encoding));
}

/// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its
/// section.  This can be done with a special directive if the target supports
/// it (e.g. cygwin) or by emitting it as an offset from a label at the start
/// of the section.
///
/// SectionLabel is a temporary label emitted at the start of the section that
/// Label lives in.
void AsmPrinter::EmitSectionOffset(const MCSymbol *Label,
                                   const MCSymbol *SectionLabel) const {
  // On COFF targets, we have to emit the special .secrel32 directive.
  if (MAI->needsDwarfSectionOffsetDirective()) {
    OutStreamer.EmitCOFFSecRel32(Label);
    return;
  }

  // Get the section that we're referring to, based on SectionLabel.
  const MCSection &Section = SectionLabel->getSection();

  // If Label has already been emitted, verify that it is in the same section as
  // section label for sanity.
  assert((!Label->isInSection() || &Label->getSection() == &Section) &&
         "Section offset using wrong section base for label");

  // If the section in question will end up with an address of 0 anyway, we can
  // just emit an absolute reference to save a relocation.
  if (Section.isBaseAddressKnownZero()) {
    OutStreamer.EmitSymbolValue(Label, 4);
    return;
  }

  // Otherwise, emit it as a label difference from the start of the section.
  EmitLabelDifference(Label, SectionLabel, 4);
}

//===----------------------------------------------------------------------===//
// Dwarf Lowering Routines
//===----------------------------------------------------------------------===//

void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
  switch (Inst.getOperation()) {
  default:
    llvm_unreachable("Unexpected instruction");
  case MCCFIInstruction::OpDefCfaOffset:
    OutStreamer.EmitCFIDefCfaOffset(Inst.getOffset());
    break;
  case MCCFIInstruction::OpDefCfa:
    OutStreamer.EmitCFIDefCfa(Inst.getRegister(), Inst.getOffset());
    break;
  case MCCFIInstruction::OpDefCfaRegister:
    OutStreamer.EmitCFIDefCfaRegister(Inst.getRegister());
    break;
  case MCCFIInstruction::OpOffset:
    OutStreamer.EmitCFIOffset(Inst.getRegister(), Inst.getOffset());
    break;
  case MCCFIInstruction::OpRegister:
    OutStreamer.EmitCFIRegister(Inst.getRegister(), Inst.getRegister2());
    break;
  case MCCFIInstruction::OpWindowSave:
    OutStreamer.EmitCFIWindowSave();
    break;
  }
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4 -*- */
/* vi: set ts=4 sw=4 noexpandtab: */

/*******************************************************************************
 * FShell 2
 * Copyright 2009 Michael Tautschnig, tautschnig@forsyte.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/

/*! \file fshell2/main/fshell2.t.cpp
 * \brief TODO
 *
 * $Id$
 * \author Michael Tautschnig <tautschnig@forsyte.de>
 * \date   Wed Apr 15 11:58:54 CEST 2009
*/

#include <diagnostics/unittest.hpp>
#include <fshell2/config/config.hpp>
#include <fshell2/config/annotations.hpp>

#include <fshell2/main/fshell2.hpp>

#include <cerrno>
#include <fstream>
#include <readline/readline.h>

#include <cbmc/src/util/config.h>
#include <cbmc/src/langapi/language_ui.h>
#include <cbmc/src/langapi/mode.h>
#include <cbmc/src/ansi-c/ansi_c_language.h>

#define TEST_COMPONENT_NAME FShell2
#define TEST_COMPONENT_NAMESPACE fshell2

FSHELL2_NAMESPACE_BEGIN;

/** @cond */
TEST_NAMESPACE_BEGIN;
TEST_COMPONENT_TEST_NAMESPACE_BEGIN;
/** @endcond */
using namespace ::diagnostics::unittest;

////////////////////////////////////////////////////////////////////////////////
/**
 * @test A test of FShell2
 *
 */
void test_single( Test_Data & data )
{
	::register_language(new_ansi_c_language);
	::cmdlinet cmdline;
	::config.set(cmdline);
	::language_uit l(cmdline);
	::optionst options;
	::goto_functionst cfg;
	::std::ostringstream os;

	::fshell2::FShell2 fshell(options, cfg);

	TEST_ASSERT(fshell.process_line(l, os, "QUIT"));
}

////////////////////////////////////////////////////////////////////////////////
/**
 * @test A test of FShell2
 *
 */
void test_interactive( Test_Data & data )
{
	::register_language(new_ansi_c_language);
	::cmdlinet cmdline;
	::config.set(cmdline);
	::language_uit l(cmdline);
	::optionst options;
	::goto_functionst cfg;
	::std::ostringstream os;

	::fshell2::FShell2 fshell(options, cfg);

	char * tempname(::strdup("/tmp/queryXXXXXX"));
	TEST_CHECK(-1 != ::mkstemp(tempname));
	::std::ofstream of(tempname);
	TEST_CHECK(of.is_open());
	of << "show sourcecode all" << ::std::endl
		<< "#define bla blubb" << ::std::endl
		<< "quit" << ::std::endl;
	of.close();

	// open the input file
	FILE * in(fopen(tempname, "r"));
	TEST_CHECK(0 == errno);
	// change the readline input to the file
	rl_instream = in;

	fshell.interactive(l, os);

	// print and check the output
	TEST_TRACE(os.str());
	::std::string data_name(::diagnostics::internal::to_string(
				"interactive_query_out_", sizeof(long) * 8, "bit"));
	TEST_ASSERT(data.compare(data_name, os.str()));

	// change back to stdin
	rl_instream = 0;
	fclose(in);

	::unlink(tempname);
	free(tempname);
}

/** @cond */
TEST_COMPONENT_TEST_NAMESPACE_END;
TEST_NAMESPACE_END;
/** @endcond */

FSHELL2_NAMESPACE_END;

TEST_SUITE_BEGIN;
TEST_NORMAL_CASE( &test_single, LEVEL_PROD );
TEST_NORMAL_CASE( &test_interactive, LEVEL_PROD );
TEST_SUITE_END;

STREAM_TEST_SYSTEM_MAIN;
<commit_msg>Added several queries to have a sensible test case<commit_after>/* -*- Mode: C++; tab-width: 4 -*- */
/* vi: set ts=4 sw=4 noexpandtab: */

/*******************************************************************************
 * FShell 2
 * Copyright 2009 Michael Tautschnig, tautschnig@forsyte.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/

/*! \file fshell2/main/fshell2.t.cpp
 * \brief TODO
 *
 * $Id$
 * \author Michael Tautschnig <tautschnig@forsyte.de>
 * \date   Wed Apr 15 11:58:54 CEST 2009
*/

#include <diagnostics/unittest.hpp>
#include <fshell2/config/config.hpp>
#include <fshell2/config/annotations.hpp>

#include <fshell2/main/fshell2.hpp>

#include <cerrno>
#include <fstream>
#include <readline/readline.h>

#include <cbmc/src/util/config.h>
#include <cbmc/src/langapi/language_ui.h>
#include <cbmc/src/langapi/mode.h>
#include <cbmc/src/ansi-c/ansi_c_language.h>

#define TEST_COMPONENT_NAME FShell2
#define TEST_COMPONENT_NAMESPACE fshell2

FSHELL2_NAMESPACE_BEGIN;

/** @cond */
TEST_NAMESPACE_BEGIN;
TEST_COMPONENT_TEST_NAMESPACE_BEGIN;
/** @endcond */
using namespace ::diagnostics::unittest;

////////////////////////////////////////////////////////////////////////////////
/**
 * @test A test of FShell2
 *
 */
void test_single( Test_Data & data )
{
	::register_language(new_ansi_c_language);
	::cmdlinet cmdline;
	::config.set(cmdline);
	::language_uit l(cmdline);
	::optionst options;
	::goto_functionst cfg;
	::std::ostringstream os;

	::fshell2::FShell2 fshell(options, cfg);

	TEST_ASSERT(fshell.process_line(l, os, "QUIT"));
}

////////////////////////////////////////////////////////////////////////////////
/**
 * @test A test of FShell2
 *
 */
void test_interactive( Test_Data & data )
{
	::register_language(new_ansi_c_language);
	::cmdlinet cmdline;
	::config.set(cmdline);
	::language_uit l(cmdline);
	::optionst options;
	::goto_functionst cfg;
	::std::ostringstream os;

	::fshell2::FShell2 fshell(options, cfg);

	char * tempname(::strdup("/tmp/queryXXXXXX"));
	TEST_CHECK(-1 != ::mkstemp(tempname));
	::std::ofstream of(tempname);
	TEST_CHECK(of.is_open());
	of << "show sourcecode all" << ::std::endl
		<< "#define bla blubb" << ::std::endl
		<< "quit" << ::std::endl;
	of.close();

	// open the input file
	FILE * in(fopen(tempname, "r"));
	TEST_CHECK(0 == errno);
	// change the readline input to the file
	rl_instream = in;

	fshell.interactive(l, os);

	// print and check the output
	TEST_TRACE(os.str());
	::std::string data_name(::diagnostics::internal::to_string(
				"interactive_query_out_", sizeof(long) * 8, "bit"));
	TEST_ASSERT(data.compare(data_name, os.str()));

	// change back to stdin
	rl_instream = 0;
	fclose(in);

	::unlink(tempname);
	free(tempname);
}

////////////////////////////////////////////////////////////////////////////////
/**
 * @test A test of FShell2
 *
 */
void test_single2( Test_Data & data )
{
	char * tempname(::strdup("/tmp/srcXXXXXX"));
	TEST_CHECK(-1 != ::mkstemp(tempname));
	::std::string tempname_str(tempname);
	tempname_str += ".c";
	::std::ofstream of(tempname_str.c_str());
	::unlink(tempname);
	::free(tempname);
	TEST_CHECK(of.is_open());
of
  << "int main(int argc, char* argv[]) {" << ::std::endl
  << "  int x=0;" << ::std::endl
  << "  if (argc>2) {" << ::std::endl
  << "    if (argc<27)" << ::std::endl
  << "L1:   --x;" << ::std::endl
  << "    else" << ::std::endl
  << "	  ++x;" << ::std::endl
  << "	}" << ::std::endl
  << "L2:" << ::std::endl
  << "  x--;" << ::std::endl
  << "  x--;" << ::std::endl
  << "  x--;" << ::std::endl
  << "  x--;" << ::std::endl
  << "  return 0;" << ::std::endl
  << "}" << ::std::endl;
	of.close();

	::register_language(new_ansi_c_language);
	::cmdlinet cmdline;
	::config.set(cmdline);
	::language_uit l(cmdline);
	::optionst options;
	::goto_functionst gf;
	//::std::ostringstream os;

	::fshell2::FShell2 fshell(options, gf);

	TEST_ASSERT(!fshell.process_line(l, ::std::cerr, ::diagnostics::internal::to_string(
					"add sourcecode \"", tempname_str, "\"").c_str()));
	::unlink(tempname_str.c_str());
	TEST_ASSERT(!fshell.process_line(l, ::std::cerr, "cover edges(@basicblockentry)"));
	TEST_ASSERT(!fshell.process_line(l, ::std::cerr, "cover edges(@basicblockentry) passing @func(main)*.@label(L1)->@label(L2).@func(main)*"));
	TEST_ASSERT(!fshell.process_line(l, ::std::cerr, "cover edges(@basicblockentry) passing @func(main)*.@label(L2)->@label(L1).@func(main)*"));
	TEST_ASSERT(!fshell.process_line(l, ::std::cerr, "cover edges(@conditionedge)->edges(@conditionedge)"));
	TEST_ASSERT(!fshell.process_line(l, ::std::cerr, "cover edges(@basicblockentry)-[ @func(main)* ]>edges(@basicblockentry)"));
	TEST_ASSERT(fshell.process_line(l, ::std::cerr, "QUIT"));
}

/** @cond */
TEST_COMPONENT_TEST_NAMESPACE_END;
TEST_NAMESPACE_END;
/** @endcond */

FSHELL2_NAMESPACE_END;

TEST_SUITE_BEGIN;
TEST_NORMAL_CASE( &test_single, LEVEL_PROD );
TEST_NORMAL_CASE( &test_interactive, LEVEL_PROD );
TEST_NORMAL_CASE( &test_single2, LEVEL_PROD );
TEST_SUITE_END;

STREAM_TEST_SYSTEM_MAIN;
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/test/testsupport/gtest_disable.h"
#include "webrtc/video_engine/test/auto_test/automated/legacy_fixture.h"
#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"

namespace {

// TODO(phoglund): These tests are generally broken on mac.
// http://code.google.com/p/webrtc/issues/detail?id=1268
class DISABLED_ON_MAC(ViEApiIntegrationTest) : public LegacyFixture {
};

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsBaseTestWithoutErrors) {
  tests_->ViEBaseAPITest();
}

// TODO(phoglund): Crashes on the v4l2loopback camera.
TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest),
       DISABLED_RunsCaptureTestWithoutErrors) {
  tests_->ViECaptureAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsCodecTestWithoutErrors) {
  tests_->ViECodecAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest),
       RunsEncryptionTestWithoutErrors) {
  tests_->ViEEncryptionAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest),
       RunsImageProcessTestWithoutErrors) {
  tests_->ViEImageProcessAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsRenderTestWithoutErrors) {
  tests_->ViERenderAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsRtpRtcpTestWithoutErrors) {
  tests_->ViERtpRtcpAPITest();
}

}  // namespace
<commit_msg>Disable flaky RunsRtpRtcpTestWithoutErrors.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/test/testsupport/gtest_disable.h"
#include "webrtc/video_engine/test/auto_test/automated/legacy_fixture.h"
#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"

namespace {

// TODO(phoglund): These tests are generally broken on mac.
// http://code.google.com/p/webrtc/issues/detail?id=1268
class DISABLED_ON_MAC(ViEApiIntegrationTest) : public LegacyFixture {
};

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsBaseTestWithoutErrors) {
  tests_->ViEBaseAPITest();
}

// TODO(phoglund): Crashes on the v4l2loopback camera.
TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest),
       DISABLED_RunsCaptureTestWithoutErrors) {
  tests_->ViECaptureAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsCodecTestWithoutErrors) {
  tests_->ViECodecAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest),
       RunsEncryptionTestWithoutErrors) {
  tests_->ViEEncryptionAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest),
       RunsImageProcessTestWithoutErrors) {
  tests_->ViEImageProcessAPITest();
}

TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsRenderTestWithoutErrors) {
  tests_->ViERenderAPITest();
}

// See: https://code.google.com/p/webrtc/issues/detail?id=2415
TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest),
       DISABLED_RunsRtpRtcpTestWithoutErrors) {
  tests_->ViERtpRtcpAPITest();
}

}  // namespace
<|endoftext|>


<commit_before>//===- SparcV9PreSelection.cpp - Specialize LLVM code for SparcV9 ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PreSelection pass which specializes LLVM code for
// the SparcV9 instruction selector, while remaining in legal portable LLVM
// form and preserving type information and type safety. This is meant to enable
// dataflow optimizations on SparcV9-specific operations such as accesses to
// constants, globals, and array indexing.
//
//===----------------------------------------------------------------------===//

#include "SparcV9Internals.h"
#include "SparcV9InstrSelectionSupport.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Scalar.h"
#include <algorithm>
using namespace llvm;

namespace {

  //===--------------------------------------------------------------------===//
  // PreSelection Pass - Specialize LLVM code for the SparcV9 instr. selector.
  //
  class PreSelection : public FunctionPass, public InstVisitor<PreSelection> {
    const TargetInstrInfo &instrInfo;

  public:
    PreSelection(const TargetMachine &T)
      : instrInfo(*T.getInstrInfo()) {}

    // runOnFunction - apply this pass to each Function
    bool runOnFunction(Function &F) {
      visit(F);
      return true;
    }
    const char *getPassName() const { return "SparcV9 Instr. Pre-selection"; }

    // These methods do the actual work of specializing code
    void visitInstruction(Instruction &I);   // common work for every instr.
    void visitGetElementPtrInst(GetElementPtrInst &I);
    void visitCallInst(CallInst &I);
    void visitPHINode(PHINode &PN);

    // Helper functions for visiting operands of every instruction
    //
    // visitOperands() works on every operand in [firstOp, lastOp-1].
    // If lastOp==0, lastOp defaults to #operands or #incoming Phi values.
    //
    // visitOneOperand() does all the work for one operand.
    //
    void visitOperands(Instruction &I, int firstOp=0);
    void visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
                         Instruction& insertBefore);
  };

#if 0
  // Register the pass...
  RegisterPass<PreSelection> X("preselect",
                               "Specialize LLVM code for a target machine"
                               createPreselectionPass);
#endif

}  // end anonymous namespace

//------------------------------------------------------------------------------
// Helper functions used by methods of class PreSelection
//------------------------------------------------------------------------------

// getGlobalAddr(): Put address of a global into a v. register.
static GetElementPtrInst* getGlobalAddr(Value* ptr, Instruction& insertBefore) {

  return (isa<GlobalVariable>(ptr))
    ? new GetElementPtrInst(ptr,
                    std::vector<Value*>(1, ConstantSInt::get(Type::LongTy, 0U)),
                    "addrOfGlobal:" + ptr->getName(), &insertBefore)
    : NULL;
}

// Wrapper on Constant::classof to use in find_if
inline static bool nonConstant(const Use& U) {
  return ! isa<Constant>(U);
}

static Instruction* DecomposeConstantExpr(ConstantExpr* CE,
                                          Instruction& insertBefore)
{
  Value *getArg1, *getArg2;

  switch(CE->getOpcode())
    {
    case Instruction::Cast:
      getArg1 = CE->getOperand(0);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
        getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
      return new CastInst(getArg1, CE->getType(), "constantCast",&insertBefore);

    case Instruction::GetElementPtr:
      assert(find_if(CE->op_begin()+1, CE->op_end(),nonConstant) == CE->op_end()
             && "All indices in ConstantExpr getelementptr must be constant!");
      getArg1 = CE->getOperand(0);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
        getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
      else if (GetElementPtrInst* gep = getGlobalAddr(getArg1, insertBefore))
        getArg1 = gep;
      return new GetElementPtrInst(getArg1,
                          std::vector<Value*>(CE->op_begin()+1, CE->op_end()),
                          "constantGEP:" + getArg1->getName(), &insertBefore);

    case Instruction::Select: {
      Value *C, *S1, *S2;
      C = CE->getOperand (0);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr> (C))
        C = DecomposeConstantExpr (CEarg, insertBefore);
      S1 = CE->getOperand (1);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr> (S1))
        S1 = DecomposeConstantExpr (CEarg, insertBefore);
      S2 = CE->getOperand (2);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr> (S2))
        S2 = DecomposeConstantExpr (CEarg, insertBefore);
      return new SelectInst (C, S1, S2, "constantSelect", &insertBefore);
    }

    default:                            // must be a binary operator
      assert(CE->getOpcode() >= Instruction::BinaryOpsBegin &&
             CE->getOpcode() <  Instruction::BinaryOpsEnd &&
             "Unhandled opcode in ConstantExpr");
      getArg1 = CE->getOperand(0);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
        getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
      getArg2 = CE->getOperand(1);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg2))
        getArg2 = DecomposeConstantExpr(CEarg, insertBefore);
      return BinaryOperator::create((Instruction::BinaryOps) CE->getOpcode(),
                                    getArg1, getArg2,
                                    "constantBinaryOp", &insertBefore);
    }
}

static inline bool ConstantTypeMustBeLoaded(const Type* CVT) {
  assert(CVT->isPrimitiveType() || isa<PointerType>(CVT));
  return !(CVT->isIntegral() || isa<PointerType>(CVT));
}

//------------------------------------------------------------------------------
// Instruction visitor methods to perform instruction-specific operations
//------------------------------------------------------------------------------
inline void
PreSelection::visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
                              Instruction& insertBefore)
{
  assert(&insertBefore != NULL && "Must have instruction to insert before.");

  if (GetElementPtrInst* gep = getGlobalAddr(Op, insertBefore)) {
    I.setOperand(opNum, gep);           // replace global operand
    return;                             // nothing more to do for this op.
  }

  Constant* CV  = dyn_cast<Constant>(Op);
  if (CV == NULL)
    return;

  if (ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) {
    // load-time constant: factor it out so we optimize as best we can
    Instruction* computeConst = DecomposeConstantExpr(CE, insertBefore);
    I.setOperand(opNum, computeConst); // replace expr operand with result
  } else if (ConstantTypeMustBeLoaded(CV->getType())) {
    // load address of constant into a register, then load the constant
    // this is now done during instruction selection
    // the constant will live in the MachineConstantPool later on
  } else if (ConstantMayNotFitInImmedField(CV, &I)) {
    // put the constant into a virtual register using a cast
    CastInst* castI = new CastInst(CV, CV->getType(), "copyConst",
                                   &insertBefore);
    I.setOperand(opNum, castI);      // replace operand with copy in v.reg.
  }
}

/// visitOperands - transform individual operands of all instructions:
/// -- Load "large" int constants into a virtual register.  What is large
///    depends on the type of instruction and on the target architecture.
/// -- For any constants that cannot be put in an immediate field,
///    load address into virtual register first, and then load the constant.
///
/// firstOp and lastOp can be used to skip leading and trailing operands.
/// If lastOp is 0, it defaults to #operands or #incoming Phi values.
///
inline void PreSelection::visitOperands(Instruction &I, int firstOp) {
  // For any instruction other than PHI, copies go just before the instr.
  for (unsigned i = firstOp, e = I.getNumOperands(); i != e; ++i)
    visitOneOperand(I, I.getOperand(i), i, I);
}

void PreSelection::visitPHINode(PHINode &PN) {
  // For a PHI, operand copies must be before the terminator of the
  // appropriate predecessor basic block.  Remaining logic is simple
  // so just handle PHIs and other instructions separately.
  //
  for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
    visitOneOperand(PN, PN.getIncomingValue(i),
                    PN.getOperandNumForIncomingValue(i),
                    *PN.getIncomingBlock(i)->getTerminator());
  // do not call visitOperands!
}

// Common work for *all* instructions.  This needs to be called explicitly
// by other visit<InstructionType> functions.
inline void PreSelection::visitInstruction(Instruction &I) {
  visitOperands(I);              // Perform operand transformations
}

// GetElementPtr instructions: check if pointer is a global
void PreSelection::visitGetElementPtrInst(GetElementPtrInst &I) {
  Instruction* curI = &I;

  // The Sparc backend doesn't handle array indexes that are not long types, so
  // insert a cast from whatever it is to long, if the sequential type index is
  // not a long already.
  unsigned Idx = 1;
  for (gep_type_iterator TI = gep_type_begin(I), E = gep_type_end(I); TI != E;
       ++TI, ++Idx)
    if (isa<SequentialType>(*TI) &&
        I.getOperand(Idx)->getType() != Type::LongTy) {
      Value *Op = I.getOperand(Idx);
      if (Op->getType()->isUnsigned())    // Must sign extend!
        Op = new CastInst(Op, Op->getType()->getSignedVersion(), "v9", &I);
      if (Op->getType() != Type::LongTy)
        Op = new CastInst(Op, Type::LongTy, "v9", &I);
      I.setOperand(Idx, Op);
    }

  // Decompose multidimensional array references
  if (I.getNumIndices() >= 2) {
    // DecomposeArrayRef() replaces I and deletes it, if successful,
    // so remember predecessor in order to find the replacement instruction.
    // Also remember the basic block in case there is no predecessor.
    Instruction* prevI = I.getPrev();
    BasicBlock* bb = I.getParent();
    if (DecomposeArrayRef(&I))
      // first instr. replacing I
      curI = cast<GetElementPtrInst>(prevI? prevI->getNext() : &bb->front());
  }

  // Perform other transformations common to all instructions
  visitInstruction(*curI);
}

void PreSelection::visitCallInst(CallInst &I) {
  // Tell visitOperands to ignore the function name if this is a direct call.
  visitOperands(I, (/*firstOp=*/ I.getCalledFunction()? 1 : 0));
}

/// createPreSelectionPass - Public entry point for the PreSelection pass
///
FunctionPass* llvm::createPreSelectionPass(const TargetMachine &TM) {
  return new PreSelection(TM);
}
<commit_msg>Include SparcV9BurgISel.h, because PreSelection uses routines from within the SparcV9 BURG instruction selector.  Eww!<commit_after>//===- SparcV9PreSelection.cpp - Specialize LLVM code for SparcV9 ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PreSelection pass which specializes LLVM code for
// the SparcV9 instruction selector, while remaining in legal portable LLVM
// form and preserving type information and type safety. This is meant to enable
// dataflow optimizations on SparcV9-specific operations such as accesses to
// constants, globals, and array indexing.
//
//===----------------------------------------------------------------------===//

#include "SparcV9Internals.h"
#include "SparcV9BurgISel.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Scalar.h"
#include <algorithm>
using namespace llvm;

namespace {

  //===--------------------------------------------------------------------===//
  // PreSelection Pass - Specialize LLVM code for the SparcV9 instr. selector.
  //
  class PreSelection : public FunctionPass, public InstVisitor<PreSelection> {
    const TargetInstrInfo &instrInfo;

  public:
    PreSelection(const TargetMachine &T)
      : instrInfo(*T.getInstrInfo()) {}

    // runOnFunction - apply this pass to each Function
    bool runOnFunction(Function &F) {
      visit(F);
      return true;
    }
    const char *getPassName() const { return "SparcV9 Instr. Pre-selection"; }

    // These methods do the actual work of specializing code
    void visitInstruction(Instruction &I);   // common work for every instr.
    void visitGetElementPtrInst(GetElementPtrInst &I);
    void visitCallInst(CallInst &I);
    void visitPHINode(PHINode &PN);

    // Helper functions for visiting operands of every instruction
    //
    // visitOperands() works on every operand in [firstOp, lastOp-1].
    // If lastOp==0, lastOp defaults to #operands or #incoming Phi values.
    //
    // visitOneOperand() does all the work for one operand.
    //
    void visitOperands(Instruction &I, int firstOp=0);
    void visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
                         Instruction& insertBefore);
  };

#if 0
  // Register the pass...
  RegisterPass<PreSelection> X("preselect",
                               "Specialize LLVM code for a target machine"
                               createPreselectionPass);
#endif

}  // end anonymous namespace

//------------------------------------------------------------------------------
// Helper functions used by methods of class PreSelection
//------------------------------------------------------------------------------

// getGlobalAddr(): Put address of a global into a v. register.
static GetElementPtrInst* getGlobalAddr(Value* ptr, Instruction& insertBefore) {

  return (isa<GlobalVariable>(ptr))
    ? new GetElementPtrInst(ptr,
                    std::vector<Value*>(1, ConstantSInt::get(Type::LongTy, 0U)),
                    "addrOfGlobal:" + ptr->getName(), &insertBefore)
    : NULL;
}

// Wrapper on Constant::classof to use in find_if
inline static bool nonConstant(const Use& U) {
  return ! isa<Constant>(U);
}

static Instruction* DecomposeConstantExpr(ConstantExpr* CE,
                                          Instruction& insertBefore)
{
  Value *getArg1, *getArg2;

  switch(CE->getOpcode())
    {
    case Instruction::Cast:
      getArg1 = CE->getOperand(0);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
        getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
      return new CastInst(getArg1, CE->getType(), "constantCast",&insertBefore);

    case Instruction::GetElementPtr:
      assert(find_if(CE->op_begin()+1, CE->op_end(),nonConstant) == CE->op_end()
             && "All indices in ConstantExpr getelementptr must be constant!");
      getArg1 = CE->getOperand(0);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
        getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
      else if (GetElementPtrInst* gep = getGlobalAddr(getArg1, insertBefore))
        getArg1 = gep;
      return new GetElementPtrInst(getArg1,
                          std::vector<Value*>(CE->op_begin()+1, CE->op_end()),
                          "constantGEP:" + getArg1->getName(), &insertBefore);

    case Instruction::Select: {
      Value *C, *S1, *S2;
      C = CE->getOperand (0);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr> (C))
        C = DecomposeConstantExpr (CEarg, insertBefore);
      S1 = CE->getOperand (1);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr> (S1))
        S1 = DecomposeConstantExpr (CEarg, insertBefore);
      S2 = CE->getOperand (2);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr> (S2))
        S2 = DecomposeConstantExpr (CEarg, insertBefore);
      return new SelectInst (C, S1, S2, "constantSelect", &insertBefore);
    }

    default:                            // must be a binary operator
      assert(CE->getOpcode() >= Instruction::BinaryOpsBegin &&
             CE->getOpcode() <  Instruction::BinaryOpsEnd &&
             "Unhandled opcode in ConstantExpr");
      getArg1 = CE->getOperand(0);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
        getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
      getArg2 = CE->getOperand(1);
      if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg2))
        getArg2 = DecomposeConstantExpr(CEarg, insertBefore);
      return BinaryOperator::create((Instruction::BinaryOps) CE->getOpcode(),
                                    getArg1, getArg2,
                                    "constantBinaryOp", &insertBefore);
    }
}

static inline bool ConstantTypeMustBeLoaded(const Type* CVT) {
  assert(CVT->isPrimitiveType() || isa<PointerType>(CVT));
  return !(CVT->isIntegral() || isa<PointerType>(CVT));
}

//------------------------------------------------------------------------------
// Instruction visitor methods to perform instruction-specific operations
//------------------------------------------------------------------------------
inline void
PreSelection::visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
                              Instruction& insertBefore)
{
  assert(&insertBefore != NULL && "Must have instruction to insert before.");

  if (GetElementPtrInst* gep = getGlobalAddr(Op, insertBefore)) {
    I.setOperand(opNum, gep);           // replace global operand
    return;                             // nothing more to do for this op.
  }

  Constant* CV  = dyn_cast<Constant>(Op);
  if (CV == NULL)
    return;

  if (ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) {
    // load-time constant: factor it out so we optimize as best we can
    Instruction* computeConst = DecomposeConstantExpr(CE, insertBefore);
    I.setOperand(opNum, computeConst); // replace expr operand with result
  } else if (ConstantTypeMustBeLoaded(CV->getType())) {
    // load address of constant into a register, then load the constant
    // this is now done during instruction selection
    // the constant will live in the MachineConstantPool later on
  } else if (ConstantMayNotFitInImmedField(CV, &I)) {
    // put the constant into a virtual register using a cast
    CastInst* castI = new CastInst(CV, CV->getType(), "copyConst",
                                   &insertBefore);
    I.setOperand(opNum, castI);      // replace operand with copy in v.reg.
  }
}

/// visitOperands - transform individual operands of all instructions:
/// -- Load "large" int constants into a virtual register.  What is large
///    depends on the type of instruction and on the target architecture.
/// -- For any constants that cannot be put in an immediate field,
///    load address into virtual register first, and then load the constant.
///
/// firstOp and lastOp can be used to skip leading and trailing operands.
/// If lastOp is 0, it defaults to #operands or #incoming Phi values.
///
inline void PreSelection::visitOperands(Instruction &I, int firstOp) {
  // For any instruction other than PHI, copies go just before the instr.
  for (unsigned i = firstOp, e = I.getNumOperands(); i != e; ++i)
    visitOneOperand(I, I.getOperand(i), i, I);
}

void PreSelection::visitPHINode(PHINode &PN) {
  // For a PHI, operand copies must be before the terminator of the
  // appropriate predecessor basic block.  Remaining logic is simple
  // so just handle PHIs and other instructions separately.
  //
  for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
    visitOneOperand(PN, PN.getIncomingValue(i),
                    PN.getOperandNumForIncomingValue(i),
                    *PN.getIncomingBlock(i)->getTerminator());
  // do not call visitOperands!
}

// Common work for *all* instructions.  This needs to be called explicitly
// by other visit<InstructionType> functions.
inline void PreSelection::visitInstruction(Instruction &I) {
  visitOperands(I);              // Perform operand transformations
}

// GetElementPtr instructions: check if pointer is a global
void PreSelection::visitGetElementPtrInst(GetElementPtrInst &I) {
  Instruction* curI = &I;

  // The Sparc backend doesn't handle array indexes that are not long types, so
  // insert a cast from whatever it is to long, if the sequential type index is
  // not a long already.
  unsigned Idx = 1;
  for (gep_type_iterator TI = gep_type_begin(I), E = gep_type_end(I); TI != E;
       ++TI, ++Idx)
    if (isa<SequentialType>(*TI) &&
        I.getOperand(Idx)->getType() != Type::LongTy) {
      Value *Op = I.getOperand(Idx);
      if (Op->getType()->isUnsigned())    // Must sign extend!
        Op = new CastInst(Op, Op->getType()->getSignedVersion(), "v9", &I);
      if (Op->getType() != Type::LongTy)
        Op = new CastInst(Op, Type::LongTy, "v9", &I);
      I.setOperand(Idx, Op);
    }

  // Decompose multidimensional array references
  if (I.getNumIndices() >= 2) {
    // DecomposeArrayRef() replaces I and deletes it, if successful,
    // so remember predecessor in order to find the replacement instruction.
    // Also remember the basic block in case there is no predecessor.
    Instruction* prevI = I.getPrev();
    BasicBlock* bb = I.getParent();
    if (DecomposeArrayRef(&I))
      // first instr. replacing I
      curI = cast<GetElementPtrInst>(prevI? prevI->getNext() : &bb->front());
  }

  // Perform other transformations common to all instructions
  visitInstruction(*curI);
}

void PreSelection::visitCallInst(CallInst &I) {
  // Tell visitOperands to ignore the function name if this is a direct call.
  visitOperands(I, (/*firstOp=*/ I.getCalledFunction()? 1 : 0));
}

/// createPreSelectionPass - Public entry point for the PreSelection pass
///
FunctionPass* llvm::createPreSelectionPass(const TargetMachine &TM) {
  return new PreSelection(TM);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "stdafx.h"

#include "runtime/parsing_and_serializing/parse_fragment.h"

#include <iostream>

#include "zorbatypes/URI.h"
#include "context/static_context.h"

#include "store/api/store.h"
#include "store/api/item.h"
#include "store/api/item_factory.h"
#include "store/api/load_properties.h"

#include "system/globalenv.h"

#include "types/schema/schema.h"
#include "types/schema/validate.h"

namespace zorba
{

/*******************************************************************************
  14.9.1 fn-zorba-xml:parse
********************************************************************************/

store::Item_t getFirstAttribute(store::Item_t node)
{
  store::Item_t attr;
  store::Iterator_t attributes = node->getAttributes();
  attributes->open();
  attributes->next(attr);
  attributes->close();
  return attr;
}

void processOptions(store::Item_t item, store::LoadProperties& props, static_context* theSctx, const QueryLoc& loc)
{
  URI lValidatedBaseUri;
  store::Item_t child, tempItem;

  if (item.getp() == NULL)
    return;

#ifndef ZORBA_NO_XMLSCHEMA
  if (item->isValidated())
  {
    if (item->getNodeName() == NULL
        ||
        item->getNodeName()->getNamespace() != static_context::ZORBA_XML_FN_OPTIONS_NS)
    {
      throw XQUERY_EXCEPTION(zerr::ZXQD0003_INCONSISTENT_PARSE_FRAGMENT_OPTIONS,
                             ERROR_PARAMS(ZED(ParseFragmentInvalidOptions)), ERROR_LOC( loc ));
    }
  }
  else
  {
    tempItem = NULL; // used as the effectiveValidationValue()'s typeName
    Validator::effectiveValidationValue(
        item,
        item,
        tempItem,
        theSctx->get_typemanager(),
        ParseConstants::val_strict,
        theSctx,
        loc);
  }
#endif

  store::Iterator_t children = item->getChildren();
  children->open();

  while (children->next(child))
  {
    if (child->getNodeKind() != store::StoreConsts::elementNode)
      continue;

    if (child->getNodeName()->getLocalName() == "base-uri")
    {
      store::Item_t attr = getFirstAttribute(child);

      try {
        lValidatedBaseUri = URI(attr->getStringValue());
      } catch (ZorbaException const& /* e */) {
        throw XQUERY_EXCEPTION(
          err::FODC0007,
          ERROR_PARAMS( attr->getStringValue() ),
          ERROR_LOC( loc )
        );
      }

      if (!lValidatedBaseUri.is_absolute()) {
        throw XQUERY_EXCEPTION(
          err::FODC0007,
          ERROR_PARAMS( lValidatedBaseUri.toString() ),
          ERROR_LOC( loc )
        );
      }

      props.setBaseUri(attr->getStringValue());
    }
    else if (child->getNodeName()->getLocalName() == "no-error")
      props.setNoError(true);
    else if (child->getNodeName()->getLocalName() == "strip-boundary-space")
      props.setStripWhitespace(true);
    else if (child->getNodeName()->getLocalName() == "schema-validate")
    {
      store::Item_t attr = getFirstAttribute(child);
      if (attr->getStringValue() == "strict")
        props.setSchemaStrictValidate(true);
      else
        props.setSchemaLaxValidate(true);
    }
    else if (child->getNodeName()->getLocalName() == "DTD-validate")
      props.setDTDValidate(true);
    else if (child->getNodeName()->getLocalName() == "DTD-load")
      props.setDTDLoad(true);
    else if (child->getNodeName()->getLocalName() == "default-DTD-attributes")
      props.setDefaultDTDAttributes(true);
    else if (child->getNodeName()->getLocalName() == "parse-external-parsed-entity")
    {
      props.setParseExternalParsedEntity(true);
      store::Item_t attr;
      store::Iterator_t attribs = child->getAttributes();
      attribs->open();
      while (attribs->next(attr))
      {
        if (attr->getNodeName()->getLocalName() == "skip-root-nodes")
          props.setSkipRootNodes(ztd::aton<xs_int>(attr->getStringValue().c_str()));
        else if (attr->getNodeName()->getLocalName() == "skip-top-level-text-nodes")
          props.setSkipTopLevelTextNodes(true);
      }
      attribs->close();
    }
    else if (child->getNodeName()->getLocalName() == "substitute-entities")
      props.setSubstituteEntities(true);
    else if (child->getNodeName()->getLocalName() == "xinclude-substitutions")
      props.setXincludeSubstitutions(true);
    else if (child->getNodeName()->getLocalName() == "remove-redundant-ns")
      props.setRemoveRedundantNS(true);
    else if (child->getNodeName()->getLocalName() == "no-CDATA")
      props.setNoCDATA(true);
    else if (child->getNodeName()->getLocalName() == "no-xinclude-nodes")
      props.setNoXIncludeNodes(true);
  }

  children->close();

  if (props.getSchemaLaxValidate() + props.getSchemaStrictValidate() +
      props.getDTDValidate() + props.getParseExternalParsedEntity() > 1)
  {
    throw XQUERY_EXCEPTION(zerr::ZXQD0003_INCONSISTENT_PARSE_FRAGMENT_OPTIONS,
                           ERROR_PARAMS(ZED(ParseFragmentOptionCombinationNotAllowed)), ERROR_LOC( loc ));
  }
}

void FnZorbaParseXmlFragmentIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
  theFragmentStream.reset();
  theProperties.reset();
  theProperties.setStoreDocument(false);
  baseUri = "";
  docUri = "";
}

bool FnZorbaParseXmlFragmentIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  store::Store& lStore = GENV.getStore();
  zstring docString;
  store::Item_t tempItem;
  bool validated = true;

  FnZorbaParseXmlFragmentIteratorState* state;
  DEFAULT_STACK_INIT(FnZorbaParseXmlFragmentIteratorState, state, planState);

  if (consumeNext(result, theChildren[0].getp(), planState))
  {
    if (result->isStreamable())
    {
      state->theFragmentStream.theStream = &result->getStream();
    }
    else
    {
      result->getStringValue2(docString);
      state->theFragmentStream.theIss = new std::istringstream(docString.c_str());
      state->theFragmentStream.theStream = state->theFragmentStream.theIss;
    }

    // read options
    consumeNext(tempItem, theChildren[1].getp(), planState);
    state->theProperties.setBaseUri(theSctx->get_base_uri());
    state->theProperties.setStoreDocument(false);
    processOptions(tempItem, state->theProperties, theSctx, loc);

    // baseURI serves both as the base URI used by the XML parser
    // to resolve relative entity references within the document,
    // and as the base URI of the document node that is returned.
    state->baseUri = state->theProperties.getBaseUri();
    state->docUri = state->theProperties.getBaseUri();

    ////////////////////////////////////////////////////////////////////////
    // External parsed entity processing
    ////////////////////////////////////////////////////////////////////////
    if (state->theProperties.getParseExternalParsedEntity())
    {
      state->theFragmentStream.root_elements_to_skip = state->theProperties.getSkipRootNodes();

      while ( ! state->theFragmentStream.stream_is_consumed())
      {
        try {
          result = lStore.loadDocument(state->baseUri, state->docUri, state->theFragmentStream, state->theProperties);
        } catch (ZorbaException const& e) {
          if ( ! state->theProperties.getNoError())
            throw XQUERY_EXCEPTION( err::FODC0006, ERROR_PARAMS("parse-xml:parse()", e.what()), ERROR_LOC( loc ));
          else
            result = NULL;
        }

        if (result == NULL)
          continue;

        // Return the children of document node
        state->theFragmentStream.children = result->getChildren();
        while (state->theFragmentStream.children->next(result) && result != NULL)
        {
          if (state->theProperties.getSkipTopLevelTextNodes() && result->getNodeKind() == store::StoreConsts::textNode)
            continue;

          STACK_PUSH(true, state);
        }
      }
    }
    ////////////////////////////////////////////////////////////////////////
    // XML document processing
    ////////////////////////////////////////////////////////////////////////
    else  // if (!state->theProperties.getEnableExtParsedEntity())
    {
      try {
        result = lStore.loadDocument(state->baseUri, state->docUri, *state->theFragmentStream.theStream, state->theProperties);
      } catch (ZorbaException const& e) {
        if ( ! state->theProperties.getNoError())
          throw XQUERY_EXCEPTION( err::FODC0006, ERROR_PARAMS("parse-xml:parse()", e.what()), ERROR_LOC( loc ));
        else
          result = NULL;
      }

      if (result != NULL)
      {
#ifndef ZORBA_NO_XMLSCHEMA
        if (state->theProperties.getSchemaLaxValidate() || state->theProperties.getSchemaStrictValidate())
        {
          try
          {
            tempItem = NULL; // used as the effectiveValidationValue()'s typeName
            validated = Validator::effectiveValidationValue(
                          result,
                          result,
                          tempItem,
                          theSctx->get_typemanager(),
                          state->theProperties.getSchemaLaxValidate() ? ParseConstants::val_lax : ParseConstants::val_strict,
                          theSctx,
                          this->loc);
          }
          catch (ZorbaException& /*e*/)
          {
            if ( ! state->theProperties.getNoError())
              throw;
            else
            {
              result = NULL;
              validated = false;
            }
          }
        }
#endif
        // Ignore the schema validation options if Zorba is built without schema support

        STACK_PUSH(validated, state);
      } // if (result != NULL)
    } // if (state->theProperties.getEnableExtParsedEntity())
  } // if (consumeNext(result, theChildren[0].getp(), planState))

  STACK_END(state);
}

/*******************************************************************************
  14.9.2 fn:parse-xml-fragment
********************************************************************************/
bool FnParseXmlFragmentIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  zstring docString;

  FnParseXmlFragmentIteratorState* state;
  DEFAULT_STACK_INIT(FnParseXmlFragmentIteratorState, state, planState);

  if (consumeNext(result, theChildren[0].getp(), planState))
  {
    if (result->isStreamable())
    {
      state->theFragmentStream.theStream = &result->getStream();
    }
    else
    {
      result->getStringValue2(docString);
      state->theFragmentStream.theIss = new std::istringstream(docString.c_str());
      state->theFragmentStream.theStream = state->theFragmentStream.theIss;
    }

    state->theProperties.setBaseUri(theSctx->get_base_uri());
    state->baseUri = state->theProperties.getBaseUri();

    state->theProperties.setParseExternalParsedEntity(true);

    while ( ! state->theFragmentStream.stream_is_consumed() )
    {
      try {
        state->theProperties.setStoreDocument(false);
        result = GENV.getStore().loadDocument(state->baseUri, state->docUri, state->theFragmentStream, state->theProperties);
      } catch (ZorbaException const& e) {
        if( ! state->theProperties.getNoError())
          throw XQUERY_EXCEPTION(err::FODC0006, ERROR_PARAMS("fn:parse-xml-fragment()", e.what() ), ERROR_LOC(loc));
        else
          result = NULL;
      }

      if(result ==NULL)
        continue;

      state->theFragmentStream.children = result->getChildren();
      while (state->theFragmentStream.children->next(result) && result != NULL)
      {
        if (result->getNodeKind() == store::StoreConsts::textNode)
          continue;
        STACK_PUSH(true, state);
      }
    }

  }

  STACK_END(state)
}

void FnParseXmlFragmentIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
  theFragmentStream.reset();
  theProperties.reset();
  theProperties.setStoreDocument(false);
  baseUri = "";
  docUri = "";
}

} /* namespace zorba */
<commit_msg>The fn:parse-xml-fragment() should return Document nodes now<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "stdafx.h"

#include "runtime/parsing_and_serializing/parse_fragment.h"

#include <iostream>

#include "zorbatypes/URI.h"
#include "context/static_context.h"

#include "store/api/store.h"
#include "store/api/item.h"
#include "store/api/item_factory.h"
#include "store/api/load_properties.h"

#include "system/globalenv.h"

#include "types/schema/schema.h"
#include "types/schema/validate.h"

namespace zorba
{

/*******************************************************************************
  14.9.1 fn-zorba-xml:parse
********************************************************************************/

store::Item_t getFirstAttribute(store::Item_t node)
{
  store::Item_t attr;
  store::Iterator_t attributes = node->getAttributes();
  attributes->open();
  attributes->next(attr);
  attributes->close();
  return attr;
}

void processOptions(store::Item_t item, store::LoadProperties& props, static_context* theSctx, const QueryLoc& loc)
{
  URI lValidatedBaseUri;
  store::Item_t child, tempItem;

  if (item.getp() == NULL)
    return;

#ifndef ZORBA_NO_XMLSCHEMA
  if (item->isValidated())
  {
    if (item->getNodeName() == NULL
        ||
        item->getNodeName()->getNamespace() != static_context::ZORBA_XML_FN_OPTIONS_NS)
    {
      throw XQUERY_EXCEPTION(zerr::ZXQD0003_INCONSISTENT_PARSE_FRAGMENT_OPTIONS,
                             ERROR_PARAMS(ZED(ParseFragmentInvalidOptions)), ERROR_LOC( loc ));
    }
  }
  else
  {
    tempItem = NULL; // used as the effectiveValidationValue()'s typeName
    Validator::effectiveValidationValue(
        item,
        item,
        tempItem,
        theSctx->get_typemanager(),
        ParseConstants::val_strict,
        theSctx,
        loc);
  }
#endif

  store::Iterator_t children = item->getChildren();
  children->open();

  while (children->next(child))
  {
    if (child->getNodeKind() != store::StoreConsts::elementNode)
      continue;

    if (child->getNodeName()->getLocalName() == "base-uri")
    {
      store::Item_t attr = getFirstAttribute(child);

      try {
        lValidatedBaseUri = URI(attr->getStringValue());
      } catch (ZorbaException const& /* e */) {
        throw XQUERY_EXCEPTION(
          err::FODC0007,
          ERROR_PARAMS( attr->getStringValue() ),
          ERROR_LOC( loc )
        );
      }

      if (!lValidatedBaseUri.is_absolute()) {
        throw XQUERY_EXCEPTION(
          err::FODC0007,
          ERROR_PARAMS( lValidatedBaseUri.toString() ),
          ERROR_LOC( loc )
        );
      }

      props.setBaseUri(attr->getStringValue());
    }
    else if (child->getNodeName()->getLocalName() == "no-error")
      props.setNoError(true);
    else if (child->getNodeName()->getLocalName() == "strip-boundary-space")
      props.setStripWhitespace(true);
    else if (child->getNodeName()->getLocalName() == "schema-validate")
    {
      store::Item_t attr = getFirstAttribute(child);
      if (attr->getStringValue() == "strict")
        props.setSchemaStrictValidate(true);
      else
        props.setSchemaLaxValidate(true);
    }
    else if (child->getNodeName()->getLocalName() == "DTD-validate")
      props.setDTDValidate(true);
    else if (child->getNodeName()->getLocalName() == "DTD-load")
      props.setDTDLoad(true);
    else if (child->getNodeName()->getLocalName() == "default-DTD-attributes")
      props.setDefaultDTDAttributes(true);
    else if (child->getNodeName()->getLocalName() == "parse-external-parsed-entity")
    {
      props.setParseExternalParsedEntity(true);
      store::Item_t attr;
      store::Iterator_t attribs = child->getAttributes();
      attribs->open();
      while (attribs->next(attr))
      {
        if (attr->getNodeName()->getLocalName() == "skip-root-nodes")
          props.setSkipRootNodes(ztd::aton<xs_int>(attr->getStringValue().c_str()));
        else if (attr->getNodeName()->getLocalName() == "skip-top-level-text-nodes")
          props.setSkipTopLevelTextNodes(true);
      }
      attribs->close();
    }
    else if (child->getNodeName()->getLocalName() == "substitute-entities")
      props.setSubstituteEntities(true);
    else if (child->getNodeName()->getLocalName() == "xinclude-substitutions")
      props.setXincludeSubstitutions(true);
    else if (child->getNodeName()->getLocalName() == "remove-redundant-ns")
      props.setRemoveRedundantNS(true);
    else if (child->getNodeName()->getLocalName() == "no-CDATA")
      props.setNoCDATA(true);
    else if (child->getNodeName()->getLocalName() == "no-xinclude-nodes")
      props.setNoXIncludeNodes(true);
  }

  children->close();

  if (props.getSchemaLaxValidate() + props.getSchemaStrictValidate() +
      props.getDTDValidate() + props.getParseExternalParsedEntity() > 1)
  {
    throw XQUERY_EXCEPTION(zerr::ZXQD0003_INCONSISTENT_PARSE_FRAGMENT_OPTIONS,
                           ERROR_PARAMS(ZED(ParseFragmentOptionCombinationNotAllowed)), ERROR_LOC( loc ));
  }
}

void FnZorbaParseXmlFragmentIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
  theFragmentStream.reset();
  theProperties.reset();
  theProperties.setStoreDocument(false);
  baseUri = "";
  docUri = "";
}

bool FnZorbaParseXmlFragmentIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  store::Store& lStore = GENV.getStore();
  zstring docString;
  store::Item_t tempItem;
  bool validated = true;

  FnZorbaParseXmlFragmentIteratorState* state;
  DEFAULT_STACK_INIT(FnZorbaParseXmlFragmentIteratorState, state, planState);

  if (consumeNext(result, theChildren[0].getp(), planState))
  {
    if (result->isStreamable())
    {
      state->theFragmentStream.theStream = &result->getStream();
    }
    else
    {
      result->getStringValue2(docString);
      state->theFragmentStream.theIss = new std::istringstream(docString.c_str());
      state->theFragmentStream.theStream = state->theFragmentStream.theIss;
    }

    // read options
    consumeNext(tempItem, theChildren[1].getp(), planState);
    state->theProperties.setBaseUri(theSctx->get_base_uri());
    state->theProperties.setStoreDocument(false);
    processOptions(tempItem, state->theProperties, theSctx, loc);

    // baseURI serves both as the base URI used by the XML parser
    // to resolve relative entity references within the document,
    // and as the base URI of the document node that is returned.
    state->baseUri = state->theProperties.getBaseUri();
    state->docUri = state->theProperties.getBaseUri();

    ////////////////////////////////////////////////////////////////////////
    // External parsed entity processing
    ////////////////////////////////////////////////////////////////////////
    if (state->theProperties.getParseExternalParsedEntity())
    {
      state->theFragmentStream.root_elements_to_skip = state->theProperties.getSkipRootNodes();

      while ( ! state->theFragmentStream.stream_is_consumed())
      {
        try {
          result = lStore.loadDocument(state->baseUri, state->docUri, state->theFragmentStream, state->theProperties);
        } catch (ZorbaException const& e) {
          if ( ! state->theProperties.getNoError())
            throw XQUERY_EXCEPTION( err::FODC0006, ERROR_PARAMS("parse-xml:parse()", e.what()), ERROR_LOC( loc ));
          else
            result = NULL;
        }

        if (result == NULL)
          continue;

        // Return the children of document node
        state->theFragmentStream.children = result->getChildren();
        while (state->theFragmentStream.children->next(result) && result != NULL)
        {
          if (state->theProperties.getSkipTopLevelTextNodes() && result->getNodeKind() == store::StoreConsts::textNode)
            continue;

          STACK_PUSH(true, state);
        }
      }
    }
    ////////////////////////////////////////////////////////////////////////
    // XML document processing
    ////////////////////////////////////////////////////////////////////////
    else  // if (!state->theProperties.getEnableExtParsedEntity())
    {
      try {
        result = lStore.loadDocument(state->baseUri, state->docUri, *state->theFragmentStream.theStream, state->theProperties);
      } catch (ZorbaException const& e) {
        if ( ! state->theProperties.getNoError())
          throw XQUERY_EXCEPTION( err::FODC0006, ERROR_PARAMS("parse-xml:parse()", e.what()), ERROR_LOC( loc ));
        else
          result = NULL;
      }

      if (result != NULL)
      {
#ifndef ZORBA_NO_XMLSCHEMA
        if (state->theProperties.getSchemaLaxValidate() || state->theProperties.getSchemaStrictValidate())
        {
          try
          {
            tempItem = NULL; // used as the effectiveValidationValue()'s typeName
            validated = Validator::effectiveValidationValue(
                          result,
                          result,
                          tempItem,
                          theSctx->get_typemanager(),
                          state->theProperties.getSchemaLaxValidate() ? ParseConstants::val_lax : ParseConstants::val_strict,
                          theSctx,
                          this->loc);
          }
          catch (ZorbaException& /*e*/)
          {
            if ( ! state->theProperties.getNoError())
              throw;
            else
            {
              result = NULL;
              validated = false;
            }
          }
        }
#endif
        // Ignore the schema validation options if Zorba is built without schema support

        STACK_PUSH(validated, state);
      } // if (result != NULL)
    } // if (state->theProperties.getEnableExtParsedEntity())
  } // if (consumeNext(result, theChildren[0].getp(), planState))

  STACK_END(state);
}

/*******************************************************************************
  14.9.2 fn:parse-xml-fragment
********************************************************************************/
bool FnParseXmlFragmentIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  zstring docString;

  FnParseXmlFragmentIteratorState* state;
  DEFAULT_STACK_INIT(FnParseXmlFragmentIteratorState, state, planState);

  if (consumeNext(result, theChildren[0].getp(), planState))
  {
    if (result->isStreamable())
    {
      state->theFragmentStream.theStream = &result->getStream();
    }
    else
    {
      result->getStringValue2(docString);
      state->theFragmentStream.theIss = new std::istringstream(docString.c_str());
      state->theFragmentStream.theStream = state->theFragmentStream.theIss;
    }

    state->theProperties.setBaseUri(theSctx->get_base_uri());
    state->baseUri = state->theProperties.getBaseUri();

    state->theProperties.setParseExternalParsedEntity(true);

    while ( ! state->theFragmentStream.stream_is_consumed() )
    {
      try {
        state->theProperties.setStoreDocument(false);
        result = GENV.getStore().loadDocument(state->baseUri, state->docUri, state->theFragmentStream, state->theProperties);
      } catch (ZorbaException const& e) {
        if( ! state->theProperties.getNoError())
          throw XQUERY_EXCEPTION(err::FODC0006, ERROR_PARAMS("fn:parse-xml-fragment()", e.what() ), ERROR_LOC(loc));
        else
          result = NULL;
      }

      if (result == NULL)
        continue;

      STACK_PUSH(true, state);
    } // while
  } // if

  STACK_END(state)
}

void FnParseXmlFragmentIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
  theFragmentStream.reset();
  theProperties.reset();
  theProperties.setStoreDocument(false);
  baseUri = "";
  docUri = "";
}

} /* namespace zorba */
<|endoftext|>


<commit_before>#include <string>
#include <boost/random/additive_combine.hpp>
#include <stan/io/dump.hpp>
#include <test/unit/mcmc/hmc/mock_hmc.hpp>
#include <stan/mcmc/hmc/hamiltonians/dense_e_metric.hpp>
#include <test/test-models/good/mcmc/hmc/hamiltonians/funnel.hpp>
#include <stan/callbacks/stream_logger.hpp>
#include <test/unit/util.hpp>
#include <gtest/gtest.h>
#include <iostream>

typedef boost::ecuyer1988 rng_t;

TEST(McmcDenseEMetric, sample_p) {
  rng_t base_rng(0);

  Eigen::Matrix2d  m(2,2);
  m(0, 0) = 3.0;
  m(1, 0) = -2.0;
  m(0, 1) = -2.0;
  m(1, 1) = 4.0;

  Eigen::Matrix2d  m_inv = m.inverse();

  stan::mcmc::mock_model model(2);

  stan::mcmc::dense_e_metric<stan::mcmc::mock_model, rng_t> metric(model);
  stan::mcmc::dense_e_point z(2);
  z.set_metric(m_inv);

  int n_samples = 1000;

  Eigen::Matrix2d sample_cov(2,2);
  sample_cov(0, 0) = 0.0;
  sample_cov(0, 1) = 0.0;
  sample_cov(1, 0) = 0.0;
  sample_cov(1, 1) = 0.0;

  for (int i = 0; i < n_samples; ++i) {
    metric.sample_p(z, base_rng);
    sample_cov(0, 0) += z.p[0] * z.p[0] / (n_samples + 0.0);
    sample_cov(0, 1) += z.p[0] * z.p[1] / (n_samples + 0.0);
    sample_cov(1, 0) += z.p[1] * z.p[0] / (n_samples + 0.0);
    sample_cov(1, 1) += z.p[1] * z.p[1] / (n_samples + 0.0);
  }

  Eigen::Matrix2d var(2,2);
  var(0, 0) = 2 * m(0, 0);
  var(1, 0) = m(1, 0) * m(1, 0) + m(1, 1) * m(0, 0);
  var(0, 1) = m(0, 1) * m(0, 1) + m(1, 1) * m(0, 0);
  var(1, 1) = 2 * m(1, 1);

  // Covariance matrix within 5sigma of expected value (comes from a Wishart distribution)
  EXPECT_TRUE(std::fabs(m(0, 0)   - sample_cov(0, 0)) < 5.0 * sqrt(var(0, 0) / n_samples));
  EXPECT_TRUE(std::fabs(m(1, 0)   - sample_cov(1, 0)) < 5.0 * sqrt(var(1, 0) / n_samples));
  EXPECT_TRUE(std::fabs(m(0, 1)   - sample_cov(0, 1)) < 5.0 * sqrt(var(0, 1) / n_samples));
  EXPECT_TRUE(std::fabs(m(1, 1)   - sample_cov(1, 1)) < 5.0 * sqrt(var(1, 1) / n_samples));
}

TEST(McmcDenseEMetric, gradients) {
  rng_t base_rng(0);

  Eigen::VectorXd q = Eigen::VectorXd::Ones(11);

  stan::mcmc::dense_e_point z(q.size());
  z.q = q;
  z.p.setOnes();

  std::fstream data_stream(std::string("").c_str(), std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  std::stringstream model_output;
  std::stringstream debug, info, warn, error, fatal;
  stan::callbacks::stream_logger logger(debug, info, warn, error, fatal);

  funnel_model_namespace::funnel_model model(data_var_context, &model_output);

  stan::mcmc::dense_e_metric<funnel_model_namespace::funnel_model, rng_t> metric(model);

  double epsilon = 1e-6;

  metric.init(z, logger);
  Eigen::VectorXd g1 = metric.dtau_dq(z, logger);

  for (int i = 0; i < z.q.size(); ++i) {

    double delta = 0;

    z.q(i) += epsilon;
    metric.update_potential(z, logger);
    delta += metric.tau(z);

    z.q(i) -= 2 * epsilon;
    metric.update_potential(z, logger);
    delta -= metric.tau(z);

    z.q(i) += epsilon;
    metric.update_potential(z, logger);

    delta /= 2 * epsilon;

    EXPECT_NEAR(delta, g1(i), epsilon);
  }

  Eigen::VectorXd g2 = metric.dtau_dp(z);

  for (int i = 0; i < z.q.size(); ++i) {

    double delta = 0;

    z.p(i) += epsilon;
    delta += metric.tau(z);

    z.p(i) -= 2 * epsilon;
    delta -= metric.tau(z);

    z.p(i) += epsilon;

    delta /= 2 * epsilon;

    EXPECT_NEAR(delta, g2(i), epsilon);
  }

  Eigen::VectorXd g3 = metric.dphi_dq(z, logger);

  for (int i = 0; i < z.q.size(); ++i) {

    double delta = 0;

    z.q(i) += epsilon;
    metric.update_potential(z, logger);
    delta += metric.phi(z);

    z.q(i) -= 2 * epsilon;
    metric.update_potential(z, logger);
    delta -= metric.phi(z);

    z.q(i) += epsilon;
    metric.update_potential(z, logger);

    delta /= 2 * epsilon;

    EXPECT_NEAR(delta, g3(i), epsilon);

  }

  EXPECT_EQ("", model_output.str());
  EXPECT_EQ("", debug.str());
  EXPECT_EQ("", info.str());
  EXPECT_EQ("", warn.str());
  EXPECT_EQ("", error.str());
  EXPECT_EQ("", fatal.str());
}

TEST(McmcDenseEMetric, streams) {
  stan::test::capture_std_streams();

  rng_t base_rng(0);

  Eigen::VectorXd q(2);
  q(0) = 5;
  q(1) = 1;

  stan::mcmc::mock_model model(q.size());

  // typedef to use within Google Test macros
  typedef stan::mcmc::dense_e_metric<stan::mcmc::mock_model, rng_t> dense_e;

  EXPECT_NO_THROW(dense_e metric(model));

  stan::test::reset_std_streams();
  EXPECT_EQ("", stan::test::cout_ss.str());
  EXPECT_EQ("", stan::test::cerr_ss.str());
}
<commit_msg>iostream just sneaks in sometimes<commit_after>#include <string>
#include <boost/random/additive_combine.hpp>
#include <stan/io/dump.hpp>
#include <test/unit/mcmc/hmc/mock_hmc.hpp>
#include <stan/mcmc/hmc/hamiltonians/dense_e_metric.hpp>
#include <test/test-models/good/mcmc/hmc/hamiltonians/funnel.hpp>
#include <stan/callbacks/stream_logger.hpp>
#include <test/unit/util.hpp>
#include <gtest/gtest.h>

typedef boost::ecuyer1988 rng_t;

TEST(McmcDenseEMetric, sample_p) {
  rng_t base_rng(0);

  Eigen::Matrix2d  m(2,2);
  m(0, 0) = 3.0;
  m(1, 0) = -2.0;
  m(0, 1) = -2.0;
  m(1, 1) = 4.0;

  Eigen::Matrix2d  m_inv = m.inverse();

  stan::mcmc::mock_model model(2);

  stan::mcmc::dense_e_metric<stan::mcmc::mock_model, rng_t> metric(model);
  stan::mcmc::dense_e_point z(2);
  z.set_metric(m_inv);

  int n_samples = 1000;

  Eigen::Matrix2d sample_cov(2,2);
  sample_cov(0, 0) = 0.0;
  sample_cov(0, 1) = 0.0;
  sample_cov(1, 0) = 0.0;
  sample_cov(1, 1) = 0.0;

  for (int i = 0; i < n_samples; ++i) {
    metric.sample_p(z, base_rng);
    sample_cov(0, 0) += z.p[0] * z.p[0] / (n_samples + 0.0);
    sample_cov(0, 1) += z.p[0] * z.p[1] / (n_samples + 0.0);
    sample_cov(1, 0) += z.p[1] * z.p[0] / (n_samples + 0.0);
    sample_cov(1, 1) += z.p[1] * z.p[1] / (n_samples + 0.0);
  }

  Eigen::Matrix2d var(2,2);
  var(0, 0) = 2 * m(0, 0);
  var(1, 0) = m(1, 0) * m(1, 0) + m(1, 1) * m(0, 0);
  var(0, 1) = m(0, 1) * m(0, 1) + m(1, 1) * m(0, 0);
  var(1, 1) = 2 * m(1, 1);

  // Covariance matrix within 5sigma of expected value (comes from a Wishart distribution)
  EXPECT_TRUE(std::fabs(m(0, 0)   - sample_cov(0, 0)) < 5.0 * sqrt(var(0, 0) / n_samples));
  EXPECT_TRUE(std::fabs(m(1, 0)   - sample_cov(1, 0)) < 5.0 * sqrt(var(1, 0) / n_samples));
  EXPECT_TRUE(std::fabs(m(0, 1)   - sample_cov(0, 1)) < 5.0 * sqrt(var(0, 1) / n_samples));
  EXPECT_TRUE(std::fabs(m(1, 1)   - sample_cov(1, 1)) < 5.0 * sqrt(var(1, 1) / n_samples));
}

TEST(McmcDenseEMetric, gradients) {
  rng_t base_rng(0);

  Eigen::VectorXd q = Eigen::VectorXd::Ones(11);

  stan::mcmc::dense_e_point z(q.size());
  z.q = q;
  z.p.setOnes();

  std::fstream data_stream(std::string("").c_str(), std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  std::stringstream model_output;
  std::stringstream debug, info, warn, error, fatal;
  stan::callbacks::stream_logger logger(debug, info, warn, error, fatal);

  funnel_model_namespace::funnel_model model(data_var_context, &model_output);

  stan::mcmc::dense_e_metric<funnel_model_namespace::funnel_model, rng_t> metric(model);

  double epsilon = 1e-6;

  metric.init(z, logger);
  Eigen::VectorXd g1 = metric.dtau_dq(z, logger);

  for (int i = 0; i < z.q.size(); ++i) {

    double delta = 0;

    z.q(i) += epsilon;
    metric.update_potential(z, logger);
    delta += metric.tau(z);

    z.q(i) -= 2 * epsilon;
    metric.update_potential(z, logger);
    delta -= metric.tau(z);

    z.q(i) += epsilon;
    metric.update_potential(z, logger);

    delta /= 2 * epsilon;

    EXPECT_NEAR(delta, g1(i), epsilon);
  }

  Eigen::VectorXd g2 = metric.dtau_dp(z);

  for (int i = 0; i < z.q.size(); ++i) {

    double delta = 0;

    z.p(i) += epsilon;
    delta += metric.tau(z);

    z.p(i) -= 2 * epsilon;
    delta -= metric.tau(z);

    z.p(i) += epsilon;

    delta /= 2 * epsilon;

    EXPECT_NEAR(delta, g2(i), epsilon);
  }

  Eigen::VectorXd g3 = metric.dphi_dq(z, logger);

  for (int i = 0; i < z.q.size(); ++i) {

    double delta = 0;

    z.q(i) += epsilon;
    metric.update_potential(z, logger);
    delta += metric.phi(z);

    z.q(i) -= 2 * epsilon;
    metric.update_potential(z, logger);
    delta -= metric.phi(z);

    z.q(i) += epsilon;
    metric.update_potential(z, logger);

    delta /= 2 * epsilon;

    EXPECT_NEAR(delta, g3(i), epsilon);

  }

  EXPECT_EQ("", model_output.str());
  EXPECT_EQ("", debug.str());
  EXPECT_EQ("", info.str());
  EXPECT_EQ("", warn.str());
  EXPECT_EQ("", error.str());
  EXPECT_EQ("", fatal.str());
}

TEST(McmcDenseEMetric, streams) {
  stan::test::capture_std_streams();

  rng_t base_rng(0);

  Eigen::VectorXd q(2);
  q(0) = 5;
  q(1) = 1;

  stan::mcmc::mock_model model(q.size());

  // typedef to use within Google Test macros
  typedef stan::mcmc::dense_e_metric<stan::mcmc::mock_model, rng_t> dense_e;

  EXPECT_NO_THROW(dense_e metric(model));

  stan::test::reset_std_streams();
  EXPECT_EQ("", stan::test::cout_ss.str());
  EXPECT_EQ("", stan::test::cerr_ss.str());
}
<|endoftext|>