<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Ali Saidi
 */

#include "base/fenv.hh"
#include "base/intmath.hh"
#include "base/misc.hh"
#include "base/random.hh"
#include "sim/serialize.hh"

using namespace std;

Random::Random()
{
    // default random seed taken from original source
    init(5489);
}

Random::Random(uint32_t s)
{
    init(s);
}

Random::Random(uint32_t init_key[], int key_length)
{
    init(init_key, key_length);
}

Random::~Random()
{
}

// To preserve the uniform random distribution between min and max,
// and allow all numbers to be represented, we generate a uniform
// random number to the nearest power of two greater than max.  If
// this number doesn't fall between 0 and max, we try again.  Anything
// else would skew the distribution.
uint32_t
Random::genrand(uint32_t max)
{
    int log = ceilLog2(max);
    int shift = (sizeof(uint32_t) * 8 - log);
    uint32_t random;

    do {
        random = genrand() >> shift;
    } while (random > max);

    return random;
}

uint64_t
Random::genrand(uint64_t max)
{
    int log = ceilLog2(max);
    int shift = (sizeof(uint64_t) * 8 - log);
    uint64_t random;

    do {
        random = (uint64_t)genrand() << 32 | (uint64_t)genrand();
        random = random >> shift;
    } while (random > max);

    return random;
}

void
Random::serialize(const string &base, ostream &os)
{
    int length = N;
    paramOut(os, base + ".mti", mti);
    paramOut(os, base + ".length", length);
    arrayParamOut(os, base + ".data", mt, length);
}

void
Random::unserialize(const string &base, Checkpoint *cp, const string &section)
{
    int length;

    paramIn(cp, section, base + ".mti", mti);
    paramIn(cp, section, base + ".length", length);
    if (length != N)
        panic("cant unserialize random number data. length != %d\n", length);

    arrayParamIn(cp, section, base + ".data", mt, length);
}

Random random_mt;
<commit_msg>BASE: Fix genrand to generate both 0s and 1s when max equals one. previously was only generating 0s.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Ali Saidi
 */

#include "base/fenv.hh"
#include "base/intmath.hh"
#include "base/misc.hh"
#include "base/random.hh"
#include "sim/serialize.hh"

using namespace std;

Random::Random()
{
    // default random seed taken from original source
    init(5489);
}

Random::Random(uint32_t s)
{
    init(s);
}

Random::Random(uint32_t init_key[], int key_length)
{
    init(init_key, key_length);
}

Random::~Random()
{
}

// To preserve the uniform random distribution between min and max,
// and allow all numbers to be represented, we generate a uniform
// random number to the nearest power of two greater than max.  If
// this number doesn't fall between 0 and max, we try again.  Anything
// else would skew the distribution.
uint32_t
Random::genrand(uint32_t max)
{
    if (max == 0)
        return 0;
    int log = ceilLog2(max) + 1;
    int shift = (sizeof(uint32_t) * 8 - log);
    uint32_t random;

    do {
        random = genrand() >> shift;
    } while (random > max);

    return random;
}

uint64_t
Random::genrand(uint64_t max)
{
    if (max == 0)
        return 0;
    int log = ceilLog2(max) + 1;
    int shift = (sizeof(uint64_t) * 8 - log);
    uint64_t random;

    do {
        random = (uint64_t)genrand() << 32 | (uint64_t)genrand();
        random = random >> shift;
    } while (random > max);

    return random;
}

void
Random::serialize(const string &base, ostream &os)
{
    int length = N;
    paramOut(os, base + ".mti", mti);
    paramOut(os, base + ".length", length);
    arrayParamOut(os, base + ".data", mt, length);
}

void
Random::unserialize(const string &base, Checkpoint *cp, const string &section)
{
    int length;

    paramIn(cp, section, base + ".mti", mti);
    paramIn(cp, section, base + ".length", length);
    if (length != N)
        panic("cant unserialize random number data. length != %d\n", length);

    arrayParamIn(cp, section, base + ".data", mt, length);
}

Random random_mt;
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: filedlg.hxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 16:58:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SVT_FILEDLG_HXX
#define _SVT_FILEDLG_HXX

#ifndef _DIALOG_HXX
#include <vcl/dialog.hxx>
#endif

class Edit;
class ImpSvFileDlg;

// --------------
// - SvPathDialog -
// --------------

class PathDialog : public ModalDialog
{
private:
    friend class FileDialog;    // Imp...

    ImpSvFileDlg*       pImpFileDlg;    // Implementation
    Link                aOKHdlLink;     // Link zum OK-Handler

protected:
    UniString           aDfltExt;       // Default - Extension

public:
                        PathDialog( Window* pParent, WinBits nWinStyle = 0, BOOL bCreateDir = TRUE );
                        ~PathDialog();

    virtual long        OK();

    void                SetPath( const UniString& rNewPath );
    void                SetPath( const Edit& rEdit );
    UniString               GetPath() const;

    void                SetOKHdl( const Link& rLink ) { aOKHdlLink = rLink; }
    const Link&         GetOKHdl() const { return aOKHdlLink; }

    virtual short       Execute();
};

// --------------
// - SvFileDialog -
// --------------

class FileDialog : public PathDialog
{
private:
    Link                aFileHdlLink;   // Link zum FileSelect-Handler
    Link                aFilterHdlLink; // Link zum FilterSelect-Handler

public:
                        FileDialog( Window* pParent, WinBits nWinStyle );
                        ~FileDialog();

    virtual void        FileSelect();
    virtual void        FilterSelect();

    void                SetDefaultExt( const UniString& rExt ) { aDfltExt = rExt; }
    const UniString&        GetDefaultExt() const { return aDfltExt; }
    void                AddFilter( const UniString& rFilter, const UniString& rType );
    void                AddFilter( const UniString& rFilter, const UniString& rType,
                                   const UniString& rSysType );
    void                RemoveFilter( const UniString& rFilter );
    void                RemoveAllFilter();
    void                SetCurFilter( const UniString& rFilter );
    UniString               GetCurFilter() const;
    USHORT              GetFilterCount() const;
    UniString               GetFilterName( USHORT nPos ) const;
    UniString               GetFilterType( USHORT nPos ) const;

    void                SetFileSelectHdl( const Link& rLink ) { aFileHdlLink = rLink; }
    const Link&         GetFileSelectHdl() const { return aFileHdlLink; }
    void                SetFilterSelectHdl( const Link& rLink ) { aFilterHdlLink = rLink; }
    const Link&         GetFilterSelectHdl() const { return aFilterHdlLink; }

    void                SetOkButtonText( const UniString& rText );
    void                SetCancelButtonText( const UniString& rText );
};

#endif  // _FILEDLG_HXX
<commit_msg>INTEGRATION: CWS visibility03 (1.1.1.1.946); FILE MERGED 2005/03/24 14:13:38 mhu 1.1.1.1.946.1: #i45006# Include svtools/(svl|svt)dllapi.h, declare symbol visibility with (SVL|SVT)_DLL(PUBLIC|PRIVATE) as appropriate; partial cleanup.<commit_after>/*************************************************************************
 *
 *  $RCSfile: filedlg.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2005-04-13 10:07:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SVT_FILEDLG_HXX
#define _SVT_FILEDLG_HXX

#ifndef INCLUDED_SVTDLLAPI_H
#include "svtools/svtdllapi.h"
#endif

#ifndef _DIALOG_HXX
#include <vcl/dialog.hxx>
#endif

class Edit;
class ImpSvFileDlg;

// --------------
// - SvPathDialog -
// --------------

class SVT_DLLPUBLIC PathDialog : public ModalDialog
{
private:
    friend class FileDialog;    // Imp...

    ImpSvFileDlg*       pImpFileDlg;    // Implementation
    Link                aOKHdlLink;     // Link zum OK-Handler

protected:
    UniString           aDfltExt;       // Default - Extension

public:
                        PathDialog( Window* pParent, WinBits nWinStyle = 0, BOOL bCreateDir = TRUE );
                        ~PathDialog();

    virtual long        OK();

    void                SetPath( const UniString& rNewPath );
    void                SetPath( const Edit& rEdit );
    UniString               GetPath() const;

    void                SetOKHdl( const Link& rLink ) { aOKHdlLink = rLink; }
    const Link&         GetOKHdl() const { return aOKHdlLink; }

    virtual short       Execute();
};

// --------------
// - SvFileDialog -
// --------------

class SVT_DLLPUBLIC FileDialog : public PathDialog
{
private:
    Link                aFileHdlLink;   // Link zum FileSelect-Handler
    Link                aFilterHdlLink; // Link zum FilterSelect-Handler

public:
                        FileDialog( Window* pParent, WinBits nWinStyle );
                        ~FileDialog();

    virtual void        FileSelect();
    virtual void        FilterSelect();

    void                SetDefaultExt( const UniString& rExt ) { aDfltExt = rExt; }
    const UniString&        GetDefaultExt() const { return aDfltExt; }
    void                AddFilter( const UniString& rFilter, const UniString& rType );
    void                AddFilter( const UniString& rFilter, const UniString& rType,
                                   const UniString& rSysType );
    void                RemoveFilter( const UniString& rFilter );
    void                RemoveAllFilter();
    void                SetCurFilter( const UniString& rFilter );
    UniString               GetCurFilter() const;
    USHORT              GetFilterCount() const;
    UniString               GetFilterName( USHORT nPos ) const;
    UniString               GetFilterType( USHORT nPos ) const;

    void                SetFileSelectHdl( const Link& rLink ) { aFileHdlLink = rLink; }
    const Link&         GetFileSelectHdl() const { return aFileHdlLink; }
    void                SetFilterSelectHdl( const Link& rLink ) { aFilterHdlLink = rLink; }
    const Link&         GetFilterSelectHdl() const { return aFilterHdlLink; }

    void                SetOkButtonText( const UniString& rText );
    void                SetCancelButtonText( const UniString& rText );
};

#endif  // _FILEDLG_HXX
<|endoftext|>


<commit_before>#include "opt/wire/wire_insn.h"

#include "design/design_util.h"
#include "design/design_tool.h"
#include "iroha/i_design.h"
#include "iroha/resource_class.h"
#include "opt/bb_set.h"
#include "opt/data_flow.h"
#include "opt/debug_annotation.h"

namespace iroha {
namespace opt {
namespace wire {

WireInsnPhase::~WireInsnPhase() {
}

Phase *WireInsnPhase::Create() {
  return new WireInsnPhase();
}

bool WireInsnPhase::ApplyForTable(ITable *table) {
  WireInsn wire_insn(table, annotation_);
  return wire_insn.Perform();
}

WireInsn::WireInsn(ITable *table, DebugAnnotation *annotation)
  : table_(table), annotation_(annotation), bset_(nullptr),
    data_flow_(nullptr) {
}

WireInsn::~WireInsn() {
  delete bset_;
  delete data_flow_;
}

bool WireInsn::Perform() {
  assign_ = DesignTool::GetResource(table_, resource::kSet);
  transition_ = DesignUtil::FindTransitionResource(table_);
  bset_ = BBSet::Create(table_, annotation_);
  data_flow_ = DataFlow::Create(bset_, annotation_);
  CollectReachingRegisters();
  for (BB *bb : bset_->bbs_) {
    BuildDependency(bb);
  }

  for (BB *bb : bset_->bbs_) {
    SplitInsnOutputBB(bb);
    ScanBBToMoveInsn(bb);
  }
  AddWireToRegisterAssignments();
  annotation_->DumpIntermediateTable(table_);
  return true;
}

void WireInsn::CollectReachingRegisters() {
  CollectUsedRegs();
  // Collect defs used somewhere in this table.
  set<RegDef *> active_defs;
  for (BB *bb : bset_->bbs_) {
    vector<RegDef *> reach_defs;
    data_flow_->GetReachDefs(bb, &reach_defs);
    auto bb_regs = used_regs_[bb];
    for (RegDef *reg_def : reach_defs) {
      if (bb_regs.find(reg_def->reg) != bb_regs.end()) {
	active_defs.insert(reg_def);
      }
    }
  }

  for (RegDef *reg_def : active_defs) {
    PerInsn *pi = GetPerInsn(reg_def->insn);
    for (IRegister *oreg : reg_def->insn->outputs_) {
      if (oreg == reg_def->reg) {
	// TODO(yt76): should be reach && used.
	// now this just checks only the reachability.
	pi->output_reach_to_other_bb_.insert(oreg);
      }
    }
  }
}

void WireInsn::CollectUsedRegs() {
  for (IState *st : table_->states_) {
    BB *bb = bset_->state_to_bb_[st];
    for (IInsn *insn : st->insns_) {
      for (IRegister *ireg : insn->inputs_) {
	used_regs_[bb].insert(ireg);
      }
    }
  }
}

void WireInsn::BuildDependency(BB *bb) {
  map<IRegister *, IInsn *> last_def_insn;
  map<IRegister *, IInsn *> last_read_insn;
  int nth_state = 0;
  for (IState *st : bb->states_) {
    for (IInsn *insn : st->insns_) {
      PerInsn *pi = GetPerInsn(insn);
      pi->nth_state = nth_state;
      // WRITE -> READ dependency
      for (IRegister *reg : insn->inputs_) {
        BuildRWDependencyPair(insn, reg, last_def_insn);
      }
      // READ -> WRITE dependency
      for (IRegister *reg : insn->outputs_) {
        BuildRWDependencyPair(insn, reg, last_read_insn);
      }
      // Update last write
      for (IRegister *reg : insn->outputs_) {
	last_def_insn[reg] = insn;
      }
      // Update last read
      for (IRegister *reg : insn->inputs_) {
	last_read_insn[reg] = insn;
      }
    }
    ++nth_state;
  }
}

void WireInsn::BuildRWDependencyPair(IInsn *insn, IRegister *reg,
				     map<IRegister *, IInsn *> &dep_map) {
  IRegister *input = reg;
  IInsn *def_insn = dep_map[input];
  if (!def_insn) {
    // not written/read in this block.
    return;
  }
  PerInsn *pi = GetPerInsn(insn);
  pi->depending_insn_[input] = def_insn;
  // adds reverse mapping too.
  PerInsn *def_insn_pi = GetPerInsn(def_insn);
  def_insn_pi->using_insns_[input].insert(insn);
}

void WireInsn::SplitInsnOutputBB(BB *bb) {
  for (IState *st : bb->states_) {
    for (IInsn *insn : st->insns_) {
      // TODO(yt76): Don't touch multi cycles insns like memory ops.
      if (insn->GetResource() == assign_) {
        PerInsn *pi = GetPerInsn(insn);
        pi->is_assign = true;
      } else {
        SplitInsnOutput(insn);
      }
    }
  }
}

void WireInsn::SplitInsnOutput(IInsn *insn) {
  for (auto it = insn->outputs_.begin(); it != insn->outputs_.end(); ++it) {
    IRegister *reg = *it;
    if (reg->IsConst() || reg->IsStateLocal()) {
      continue;
    }
    IRegister *wire_reg =
      new IRegister(table_, reg->GetName() + "_" + Util::Itoa(insn->GetId()));
    wire_reg->SetStateLocal(true);
    table_->registers_.push_back(wire_reg);
    AddWireToRegMapping(insn, wire_reg, reg);
    *it = wire_reg;
  }
}

void WireInsn::AddWireToRegMapping(IInsn *insn, IRegister *wire,
				   IRegister *reg) {
  PerInsn *pi = GetPerInsn(insn);
  pi->wire_to_register_[wire] = reg;
  pi->register_to_wire_[reg] = wire;
}

void WireInsn::ScanBBToMoveInsn(BB *bb) {
  for (int target = 0; target < bb->states_.size() - 1; ++target) {
    for (int pos = target + 1; pos < bb->states_.size(); ++pos) {
      vector<IInsn *> movable_insns;
      IState *src_st = bb->states_[pos];
      for (IInsn *insn : src_st->insns_) {
	if (CanMoveInsn(insn, bb, target)) {
	  movable_insns.push_back(insn);
	}
      }
      for (IInsn *insn : movable_insns) {
	MoveInsn(insn, bb, target);
      }
    }
  }
}

bool WireInsn::CanMoveInsn(IInsn *insn, BB *bb, int target_pos) {
  if (insn->GetResource() == transition_) {
    return false;
  }
  IState *target_st = bb->states_[target_pos];
  if (!CanUseResourceInState(target_st, insn->GetResource())) {
    return false;
  }
  PerInsn *pi = GetPerInsn(insn);
  int max_pos = 0;
  // Check input dependency
  for (auto it : pi->depending_insn_) {
    PerInsn *src_pi = GetPerInsn(it.second);
    if (src_pi->nth_state > max_pos) {
      max_pos = src_pi->nth_state;
    }
  }
  if (max_pos <= target_pos) {
    return true;
  }
  return false;
}

void WireInsn::MoveInsn(IInsn *insn, BB *bb, int target_pos) {
  PerInsn *pi = GetPerInsn(insn);
  IState *src_st = bb->states_[pi->nth_state];
  IState *dst_st = bb->states_[target_pos];
  DesignTool::MoveInsn(insn, src_st, dst_st);
  pi->nth_state = target_pos;
  //  for (IRegister *ireg : insn->inputs_) {
  for (auto it = insn->inputs_.begin(); it != insn->inputs_.end(); ++it) {
    IRegister *ireg = *it;
    IInsn *src_insn = pi->depending_insn_[ireg];
    if (!src_insn) {
      continue;
    }
    PerInsn *src_pi = GetPerInsn(src_insn);
    if (src_pi->nth_state < target_pos) {
      // This register was an output in previous state,
      // so the wire is not avaialble.
      continue;
    }
    IRegister *alt_input = src_pi->register_to_wire_[ireg];
    if (alt_input == nullptr && src_pi->is_assign) {
      alt_input = *(src_insn->inputs_.begin());
    }
    if (alt_input != nullptr) {
      *it = alt_input;
    }
  }
}

bool WireInsn::CanUseResourceInState(IState *st, IResource *resource) {
  for (IInsn *target_insn : st->insns_) {
    if (resource->GetClass()->IsExclusive() &&
	resource == target_insn->GetResource()) {
      return false;
    }
  }
  return true;
}

void WireInsn::AddWireToRegisterAssignments() {
  for (IState *st : table_->states_) {
    vector<IInsn *> new_assign_insn;
    for (IInsn *insn : st->insns_) {
      PerInsn *pi = GetPerInsn(insn);
      for (IRegister *maybe_wire : insn->outputs_) {
	IRegister *orig_reg = pi->wire_to_register_[maybe_wire];
	if (orig_reg) {
	  const bool used_later = IsUsedLaterInThisBB(insn, orig_reg);
	  const bool reach_to_other_bb =
	    pi->output_reach_to_other_bb_.find(orig_reg) !=
	    pi->output_reach_to_other_bb_.end();
	  if (used_later || reach_to_other_bb) {
	    IInsn *assign_insn = new IInsn(assign_);
	    assign_insn->inputs_.push_back(maybe_wire);
	    assign_insn->outputs_.push_back(orig_reg);
	    new_assign_insn.push_back(assign_insn);
	  }
	}
      }
    }
    for (IInsn *insn : new_assign_insn) {
      st->insns_.push_back(insn);
    }
  }
}

bool WireInsn::IsUsedLaterInThisBB(IInsn *insn, IRegister *output) {
  PerInsn *pi = GetPerInsn(insn);
  map<IRegister *, set<IInsn *> >::iterator it = pi->using_insns_.find(output);
  if (it == pi->using_insns_.end()) {
    return false;
  }
  set<IInsn *> &users = it->second;
  for (IInsn *insn : users) {
    PerInsn *user_pi = GetPerInsn(insn);
    if (user_pi->nth_state > pi->nth_state) {
      return true;
    }
  }
  return false;
}

WireInsn::PerInsn *WireInsn::GetPerInsn(IInsn *insn) {
  PerInsn *pi = per_insn_map_[insn];
  if (pi == nullptr) {
    pi = new PerInsn;
    per_insn_map_[insn] = pi;
  }
  return pi;
}

}  // namespace wire
}  // namespace opt
}  // namespace iroha
<commit_msg>Add a missing null check on wire_insn optimizer.<commit_after>#include "opt/wire/wire_insn.h"

#include "design/design_util.h"
#include "design/design_tool.h"
#include "iroha/i_design.h"
#include "iroha/resource_class.h"
#include "opt/bb_set.h"
#include "opt/data_flow.h"
#include "opt/debug_annotation.h"

namespace iroha {
namespace opt {
namespace wire {

WireInsnPhase::~WireInsnPhase() {
}

Phase *WireInsnPhase::Create() {
  return new WireInsnPhase();
}

bool WireInsnPhase::ApplyForTable(ITable *table) {
  WireInsn wire_insn(table, annotation_);
  return wire_insn.Perform();
}

WireInsn::WireInsn(ITable *table, DebugAnnotation *annotation)
  : table_(table), annotation_(annotation), bset_(nullptr),
    data_flow_(nullptr) {
}

WireInsn::~WireInsn() {
  delete bset_;
  delete data_flow_;
}

bool WireInsn::Perform() {
  assign_ = DesignTool::GetResource(table_, resource::kSet);
  transition_ = DesignUtil::FindTransitionResource(table_);
  bset_ = BBSet::Create(table_, annotation_);
  data_flow_ = DataFlow::Create(bset_, annotation_);
  CollectReachingRegisters();
  for (BB *bb : bset_->bbs_) {
    BuildDependency(bb);
  }

  for (BB *bb : bset_->bbs_) {
    SplitInsnOutputBB(bb);
    ScanBBToMoveInsn(bb);
  }
  AddWireToRegisterAssignments();
  if (annotation_ != nullptr) {
    annotation_->DumpIntermediateTable(table_);
  }
  return true;
}

void WireInsn::CollectReachingRegisters() {
  CollectUsedRegs();
  // Collect defs used somewhere in this table.
  set<RegDef *> active_defs;
  for (BB *bb : bset_->bbs_) {
    vector<RegDef *> reach_defs;
    data_flow_->GetReachDefs(bb, &reach_defs);
    auto bb_regs = used_regs_[bb];
    for (RegDef *reg_def : reach_defs) {
      if (bb_regs.find(reg_def->reg) != bb_regs.end()) {
	active_defs.insert(reg_def);
      }
    }
  }

  for (RegDef *reg_def : active_defs) {
    PerInsn *pi = GetPerInsn(reg_def->insn);
    for (IRegister *oreg : reg_def->insn->outputs_) {
      if (oreg == reg_def->reg) {
	// TODO(yt76): should be reach && used.
	// now this just checks only the reachability.
	pi->output_reach_to_other_bb_.insert(oreg);
      }
    }
  }
}

void WireInsn::CollectUsedRegs() {
  for (IState *st : table_->states_) {
    BB *bb = bset_->state_to_bb_[st];
    for (IInsn *insn : st->insns_) {
      for (IRegister *ireg : insn->inputs_) {
	used_regs_[bb].insert(ireg);
      }
    }
  }
}

void WireInsn::BuildDependency(BB *bb) {
  map<IRegister *, IInsn *> last_def_insn;
  map<IRegister *, IInsn *> last_read_insn;
  int nth_state = 0;
  for (IState *st : bb->states_) {
    for (IInsn *insn : st->insns_) {
      PerInsn *pi = GetPerInsn(insn);
      pi->nth_state = nth_state;
      // WRITE -> READ dependency
      for (IRegister *reg : insn->inputs_) {
        BuildRWDependencyPair(insn, reg, last_def_insn);
      }
      // READ -> WRITE dependency
      for (IRegister *reg : insn->outputs_) {
        BuildRWDependencyPair(insn, reg, last_read_insn);
      }
      // Update last write
      for (IRegister *reg : insn->outputs_) {
	last_def_insn[reg] = insn;
      }
      // Update last read
      for (IRegister *reg : insn->inputs_) {
	last_read_insn[reg] = insn;
      }
    }
    ++nth_state;
  }
}

void WireInsn::BuildRWDependencyPair(IInsn *insn, IRegister *reg,
				     map<IRegister *, IInsn *> &dep_map) {
  IRegister *input = reg;
  IInsn *def_insn = dep_map[input];
  if (!def_insn) {
    // not written/read in this block.
    return;
  }
  PerInsn *pi = GetPerInsn(insn);
  pi->depending_insn_[input] = def_insn;
  // adds reverse mapping too.
  PerInsn *def_insn_pi = GetPerInsn(def_insn);
  def_insn_pi->using_insns_[input].insert(insn);
}

void WireInsn::SplitInsnOutputBB(BB *bb) {
  for (IState *st : bb->states_) {
    for (IInsn *insn : st->insns_) {
      // TODO(yt76): Don't touch multi cycles insns like memory ops.
      if (insn->GetResource() == assign_) {
        PerInsn *pi = GetPerInsn(insn);
        pi->is_assign = true;
      } else {
        SplitInsnOutput(insn);
      }
    }
  }
}

void WireInsn::SplitInsnOutput(IInsn *insn) {
  for (auto it = insn->outputs_.begin(); it != insn->outputs_.end(); ++it) {
    IRegister *reg = *it;
    if (reg->IsConst() || reg->IsStateLocal()) {
      continue;
    }
    IRegister *wire_reg =
      new IRegister(table_, reg->GetName() + "_" + Util::Itoa(insn->GetId()));
    wire_reg->SetStateLocal(true);
    table_->registers_.push_back(wire_reg);
    AddWireToRegMapping(insn, wire_reg, reg);
    *it = wire_reg;
  }
}

void WireInsn::AddWireToRegMapping(IInsn *insn, IRegister *wire,
				   IRegister *reg) {
  PerInsn *pi = GetPerInsn(insn);
  pi->wire_to_register_[wire] = reg;
  pi->register_to_wire_[reg] = wire;
}

void WireInsn::ScanBBToMoveInsn(BB *bb) {
  for (int target = 0; target < bb->states_.size() - 1; ++target) {
    for (int pos = target + 1; pos < bb->states_.size(); ++pos) {
      vector<IInsn *> movable_insns;
      IState *src_st = bb->states_[pos];
      for (IInsn *insn : src_st->insns_) {
	if (CanMoveInsn(insn, bb, target)) {
	  movable_insns.push_back(insn);
	}
      }
      for (IInsn *insn : movable_insns) {
	MoveInsn(insn, bb, target);
      }
    }
  }
}

bool WireInsn::CanMoveInsn(IInsn *insn, BB *bb, int target_pos) {
  if (insn->GetResource() == transition_) {
    return false;
  }
  IState *target_st = bb->states_[target_pos];
  if (!CanUseResourceInState(target_st, insn->GetResource())) {
    return false;
  }
  PerInsn *pi = GetPerInsn(insn);
  int max_pos = 0;
  // Check input dependency
  for (auto it : pi->depending_insn_) {
    PerInsn *src_pi = GetPerInsn(it.second);
    if (src_pi->nth_state > max_pos) {
      max_pos = src_pi->nth_state;
    }
  }
  if (max_pos <= target_pos) {
    return true;
  }
  return false;
}

void WireInsn::MoveInsn(IInsn *insn, BB *bb, int target_pos) {
  PerInsn *pi = GetPerInsn(insn);
  IState *src_st = bb->states_[pi->nth_state];
  IState *dst_st = bb->states_[target_pos];
  DesignTool::MoveInsn(insn, src_st, dst_st);
  pi->nth_state = target_pos;
  //  for (IRegister *ireg : insn->inputs_) {
  for (auto it = insn->inputs_.begin(); it != insn->inputs_.end(); ++it) {
    IRegister *ireg = *it;
    IInsn *src_insn = pi->depending_insn_[ireg];
    if (!src_insn) {
      continue;
    }
    PerInsn *src_pi = GetPerInsn(src_insn);
    if (src_pi->nth_state < target_pos) {
      // This register was an output in previous state,
      // so the wire is not avaialble.
      continue;
    }
    IRegister *alt_input = src_pi->register_to_wire_[ireg];
    if (alt_input == nullptr && src_pi->is_assign) {
      alt_input = *(src_insn->inputs_.begin());
    }
    if (alt_input != nullptr) {
      *it = alt_input;
    }
  }
}

bool WireInsn::CanUseResourceInState(IState *st, IResource *resource) {
  for (IInsn *target_insn : st->insns_) {
    if (resource->GetClass()->IsExclusive() &&
	resource == target_insn->GetResource()) {
      return false;
    }
  }
  return true;
}

void WireInsn::AddWireToRegisterAssignments() {
  for (IState *st : table_->states_) {
    vector<IInsn *> new_assign_insn;
    for (IInsn *insn : st->insns_) {
      PerInsn *pi = GetPerInsn(insn);
      for (IRegister *maybe_wire : insn->outputs_) {
	IRegister *orig_reg = pi->wire_to_register_[maybe_wire];
	if (orig_reg) {
	  const bool used_later = IsUsedLaterInThisBB(insn, orig_reg);
	  const bool reach_to_other_bb =
	    pi->output_reach_to_other_bb_.find(orig_reg) !=
	    pi->output_reach_to_other_bb_.end();
	  if (used_later || reach_to_other_bb) {
	    IInsn *assign_insn = new IInsn(assign_);
	    assign_insn->inputs_.push_back(maybe_wire);
	    assign_insn->outputs_.push_back(orig_reg);
	    new_assign_insn.push_back(assign_insn);
	  }
	}
      }
    }
    for (IInsn *insn : new_assign_insn) {
      st->insns_.push_back(insn);
    }
  }
}

bool WireInsn::IsUsedLaterInThisBB(IInsn *insn, IRegister *output) {
  PerInsn *pi = GetPerInsn(insn);
  map<IRegister *, set<IInsn *> >::iterator it = pi->using_insns_.find(output);
  if (it == pi->using_insns_.end()) {
    return false;
  }
  set<IInsn *> &users = it->second;
  for (IInsn *insn : users) {
    PerInsn *user_pi = GetPerInsn(insn);
    if (user_pi->nth_state > pi->nth_state) {
      return true;
    }
  }
  return false;
}

WireInsn::PerInsn *WireInsn::GetPerInsn(IInsn *insn) {
  PerInsn *pi = per_insn_map_[insn];
  if (pi == nullptr) {
    pi = new PerInsn;
    per_insn_map_[insn] = pi;
  }
  return pi;
}

}  // namespace wire
}  // namespace opt
}  // namespace iroha
<|endoftext|>


<commit_before>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                                   Extrae                                  *
 *              Instrumentation package for parallel applications            *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in 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 LGPL for more details.   *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public License  *
 * along with this library; if not, write to the Free Software Foundation,   *
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *\
 | @file: $HeadURL: https://svn.bsc.es/repos/ptools/extrae/trunk/src/others/papi_best_set.c $
 | @last_commit: $Date: 2011-11-30 11:58:56 +0100 (mié, 30 nov 2011) $
 | @version:     $Revision: 890 $
\* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
#include "common.h"

static char UNUSED rcsid[] = "$Id: papi_best_set.c 890 2011-11-30 10:58:56Z harald $";

#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_ASSERT_H
# include <assert.h>
#endif

#include <papi.h>

#include <vector>
#include <string>
#include <iostream>
#include <bitset>

using namespace std;

#define MAXBITSET 128 // Increase this if you want to allow more than this value of variable counters

static vector<string> omnipresentCounters, Counters;

bool checkCounters (const vector<string> &omnicounters,
	const vector<string> &counters, const bitset<MAXBITSET> &bitmask)
{
	unsigned i;
	bool valid = true;
	int EventSet = PAPI_NULL;

	if (PAPI_create_eventset(&EventSet) != PAPI_OK)
		return false;

	for (i = 0; i < omnicounters.size() && valid; i++)
		valid = PAPI_add_named_event (EventSet, (char*)omnicounters[i].c_str()) == PAPI_OK;

	if (!valid)
	{
		cerr << "Error! Omnipresent counters cannot be added together!" << endl;
		exit (-1);
	}

	for (i = 0; i < counters.size() && valid; i++)
		if (bitmask.test(i))
			valid = PAPI_add_named_event (EventSet, (char*)counters[i].c_str()) == PAPI_OK;

	PAPI_cleanup_eventset (EventSet);
	PAPI_destroy_eventset (&EventSet);

	return valid;
}

/*   CheckMaxEventSet

     Search the eventset with the maximum events added.
     Uses a bitmask to generate all the possible combinations.
*/
void CheckMaxEventSet (unsigned neventset, const vector<string> &omnicounters,
	vector<string> &counters)
{
	assert (counters.size() < 63); // We cannot handle values larger than 64 bits!

	bitset<MAXBITSET> bitmask (0);
	bitset<MAXBITSET> max_value (1ULL << counters.size());
	bitset<MAXBITSET> max_combination;

	while (bitmask != max_value)
	{
		unsigned bitvalue = bitmask.to_ulong();
		if (bitmask.count() <= 8-omnicounters.size()) /* Supported per Extrae */
			if (checkCounters (omnicounters, counters, bitmask))
				if (bitmask.count() > max_combination.count())
					max_combination = bitmask;

		/* If reached Extrae's limit, stop here */
		if (max_combination.count() == 8-omnicounters.size())
			break;
#if 0
		string mystring = bitmask.to_string<char,string::traits_type,string::allocator_type>();
		cout << "bits: " << mystring << endl;
#endif
		bitmask = bitvalue+1;
	}
#if 0
	string mystring = max_combination.to_string<char,string::traits_type,string::allocator_type>();
	cout << "max combination bits: " << mystring << endl;
#else

	/* Show selected counters  */
	cout << "<!-- counter set " << neventset << " -->" << endl;
	cout << "<set enabled=\"yes\" domain=\"all\" changeat-time=\"500000us\">" << endl
	     << "  ";

	if (omnicounters.size() > 0)
	{
		for (size_t i = 0; i < omnicounters.size()-1; i++)
			cout << omnicounters[i] << ",";
		cout << omnicounters[omnicounters.size()-1];
	}

	if (max_combination.count() > 0)
	{
		if (omnicounters.size() > 0)
			cout << ",";

		bitset<MAXBITSET> max = max_combination;
		size_t i = 0;
		while (i < max.size() && max.count() > 0)
		{
			if (max.test(i))
			{
				max.flip (i);
				if (max.count() > 0)
					cout << counters[i] << ",";
				else
					cout << counters[i];
			}
			i++;
		}

		/* Remove already used counters from the counter list */
		max = max_combination;
		i = MAXBITSET-1;
		while (1)
		{
			if (max.test(i))
				counters.erase (counters.begin()+i);
			if (i > 0)
				i--;
			else
				break;
		}
	}
	cout << endl << "</set>" << endl;
#endif
}

void addCounters (char *ctr, vector<string> & counters)
{
	string s_ctr (ctr);

	size_t position = s_ctr.find (',');
	while (string::npos != position)
	{
		counters.push_back (s_ctr.substr (0, position));
		s_ctr = s_ctr.substr (position+1);
		position  = s_ctr.find (',');
	}
	counters.push_back (s_ctr);
}

unsigned dumpEventCtrInfo (const char *ctr)
{
	PAPI_event_info_t info;
	int Event;
	int rc;
	char EventName[PAPI_MAX_STR_LEN];

	rc = PAPI_event_name_to_code ((char*)ctr, &Event);
	if (rc != PAPI_OK)
	{
		cout << "Warning! Counter '" << ctr << "' is not available" << endl;
		return 0;
	}

	/* Get the event name */
	rc = PAPI_event_code_to_name (Event, EventName);
	if (rc != PAPI_OK)
		strcpy (EventName, "unknown");

	/* Get event info,
	   native counters can have info.count == 0 */
	rc = PAPI_get_event_info (Event, &info);
	if (rc != PAPI_OK)
	{
		cout << "Warning! Counter '" << ctr << "' is not available" << endl;
		return 0;
	}
	else if (info.count == 0 && (Event & PAPI_NATIVE_MASK) == 0)
	{
		cout << "Warning! Counter '" << ctr << "' is not available" << endl;
		return 0;
	}
	else
	{
		cout << "Counter " << ctr << " (code " << std::hex << Event << std::dec << "): ";
		if (Event&PAPI_NATIVE_MASK)
			cout << "native";
		else
			cout << "derived";
		if (!(Event&PAPI_NATIVE_MASK))
			cout << " (depends on " << info.count << " native counters)";
		cout << endl;
	}
	return 1;
}

int main (int argc, char *argv[])
{
	int rc;
	int i;
	vector<string> omnipresentCounters_tmp, Counters_tmp;

	if (argc < 2)
	{
		cerr << "Usage for " << basename (argv[0]) << endl << endl
		     << "{omnipresent ctr}          ensures that ctr appears in every resulting group" << endl
		     << "{omnipresent ctr1,..,ctrN} ensures that ctr1-ctrN appear in every resulting group" << endl
			 << "ctr                        requests that ctr appears in 1 resulting group" << endl
			 << "ctr1,..,ctrN               requests that ctr1-ctrN appear in 1 resultign group" << endl;

		return -1;
	}

	rc = PAPI_library_init(PAPI_VER_CURRENT);
	if (rc != PAPI_VER_CURRENT && rc > 0)
	{
		cerr << "Error: PAPI library version mismatch!" << endl;
		return -2;
	}

	cout << "This binary was built using PAPI found in " << PAPI_HOME << endl;

	i = 1;
	while (i < argc)
	{
		string param = argv[i];

		if (param == "omnipresent")
		{
			i++;
			if (i < argc)
				addCounters (argv[i], omnipresentCounters_tmp);
		}
		else
			addCounters (argv[i], Counters_tmp);

		i++;
	}

	if (omnipresentCounters.size() >= 8)
	{
		cerr << "Sorry, Extrae is limited to 8 performance counters and you have requested " << omnipresentCounters.size() << " omnipresent counters..." << endl;
		exit (-1);
	}

	vector<string>::iterator it;
	unsigned num_events = 0;
	cout << endl << "** Checking the following omnipresent counters:" << endl;
	for (it = omnipresentCounters_tmp.begin(); it != omnipresentCounters_tmp.end(); it++)
		if (dumpEventCtrInfo ((*it).c_str()))
		{
			omnipresentCounters.push_back (*it);
			num_events++;
		}
	cout << endl << "** Checking the following counters:" << endl;
	for (it = Counters_tmp.begin(); it != Counters_tmp.end(); it++)
		if (dumpEventCtrInfo ((*it).c_str()))
		{
			Counters.push_back (*it);
			num_events++;
		}

	if (num_events == 0)
	{
		cout << endl <<
		     "Sorry, no hardware counters were given or the given are not available." << endl <<
		     "Check " << PAPI_HOME << "/bin/papi_avail or" << endl <<
		     "      " << PAPI_HOME << "/bin/papi_native_avail" << endl <<
		     "to get a list from the available counters in the system." << endl;
		exit (-2);
	}
	else if (num_events >= 64)
	{
		cerr << endl <<
		  "Sorry, we cannot handle 64 or more performance counters at this moment." << endl;
		exit (-3);
	}

	cout << endl;

	size_t ncounters, prevncounters = Counters.size();
	unsigned neventset = 1;
	do
	{
		CheckMaxEventSet (neventset++, omnipresentCounters, Counters);
		ncounters = Counters.size();

		if (prevncounters == ncounters && prevncounters > 0)
		{
			cout << endl <<
			  "Caution, for some reason the following hardware counters cannot be added in an eventset." << endl;
			for (size_t s = 0; s < Counters.size(); s++)
				cout << Counters[i] << " ";
			cout << endl;
			break;
		}
		else
			prevncounters = ncounters;

	} while (Counters.size() > 0);

	return 0;
}

<commit_msg>Fix missing header Fix compilation for PAPI x, where x < 5<commit_after>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                                   Extrae                                  *
 *              Instrumentation package for parallel applications            *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in 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 LGPL for more details.   *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public License  *
 * along with this library; if not, write to the Free Software Foundation,   *
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *\
 | @file: $HeadURL: https://svn.bsc.es/repos/ptools/extrae/trunk/src/others/papi_best_set.c $
 | @last_commit: $Date: 2011-11-30 11:58:56 +0100 (mié, 30 nov 2011) $
 | @version:     $Revision: 890 $
\* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
#include "common.h"

static char UNUSED rcsid[] = "$Id: papi_best_set.c 890 2011-11-30 10:58:56Z harald $";

#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_ASSERT_H
# include <assert.h>
#endif
#ifdef HAVE_LIBGEN_H
# include <libgen.h>
#endif

#include <papi.h>

#include <vector>
#include <string>
#include <iostream>
#include <bitset>

using namespace std;

#define MAXBITSET 128 // Increase this if you want to allow more than this value of variable counters

static vector<string> omnipresentCounters, Counters;

#if PAPI_VERSION_MAJOR(PAPI_VERSION) < 5
/* Provide our own PAPI_add_named_event if we're on PAPI pre-5 */
static int PAPI_add_named_event (int EventSet, char *counter)
{
	int rc;
	int EventCode;

	if ((rc = PAPI_event_name_to_code (counter, &EventCode)) != PAPI_OK)
		return rc;

	return PAPI_add_event (EventSet, EventCode);
}
#endif

static bool checkCounters (const vector<string> &omnicounters,
	const vector<string> &counters, const bitset<MAXBITSET> &bitmask)
{
	unsigned i;
	bool valid = true;
	int EventSet = PAPI_NULL;

	if (PAPI_create_eventset(&EventSet) != PAPI_OK)
		return false;

	for (i = 0; i < omnicounters.size() && valid; i++)
		valid = PAPI_add_named_event (EventSet, (char*)omnicounters[i].c_str()) == PAPI_OK;

	if (!valid)
	{
		cerr << "Error! Omnipresent counters cannot be added together!" << endl;
		exit (-1);
	}

	for (i = 0; i < counters.size() && valid; i++)
		if (bitmask.test(i))
			valid = PAPI_add_named_event (EventSet, (char*)counters[i].c_str()) == PAPI_OK;

	PAPI_cleanup_eventset (EventSet);
	PAPI_destroy_eventset (&EventSet);

	return valid;
}

/*   CheckMaxEventSet

     Search the eventset with the maximum events added.
     Uses a bitmask to generate all the possible combinations.
*/
static void CheckMaxEventSet (unsigned neventset, const vector<string> &omnicounters,
	vector<string> &counters)
{
	assert (counters.size() < 63); // We cannot handle values larger than 64 bits!

	bitset<MAXBITSET> bitmask (0);
	bitset<MAXBITSET> max_value (1ULL << counters.size());
	bitset<MAXBITSET> max_combination;

	while (bitmask != max_value)
	{
		unsigned bitvalue = bitmask.to_ulong();
		if (bitmask.count() <= 8-omnicounters.size()) /* Supported per Extrae */
			if (checkCounters (omnicounters, counters, bitmask))
				if (bitmask.count() > max_combination.count())
					max_combination = bitmask;

		/* If reached Extrae's limit, stop here */
		if (max_combination.count() == 8-omnicounters.size())
			break;
#if 0
		string mystring = bitmask.to_string<char,string::traits_type,string::allocator_type>();
		cout << "bits: " << mystring << endl;
#endif
		bitmask = bitvalue+1;
	}
#if 0
	string mystring = max_combination.to_string<char,string::traits_type,string::allocator_type>();
	cout << "max combination bits: " << mystring << endl;
#else

	/* Show selected counters  */
	cout << "<!-- counter set " << neventset << " -->" << endl;
	cout << "<set enabled=\"yes\" domain=\"all\" changeat-time=\"500000us\">" << endl
	     << "  ";

	if (omnicounters.size() > 0)
	{
		for (size_t i = 0; i < omnicounters.size()-1; i++)
			cout << omnicounters[i] << ",";
		cout << omnicounters[omnicounters.size()-1];
	}

	if (max_combination.count() > 0)
	{
		if (omnicounters.size() > 0)
			cout << ",";

		bitset<MAXBITSET> max = max_combination;
		size_t i = 0;
		while (i < max.size() && max.count() > 0)
		{
			if (max.test(i))
			{
				max.flip (i);
				if (max.count() > 0)
					cout << counters[i] << ",";
				else
					cout << counters[i];
			}
			i++;
		}

		/* Remove already used counters from the counter list */
		max = max_combination;
		i = MAXBITSET-1;
		while (1)
		{
			if (max.test(i))
				counters.erase (counters.begin()+i);
			if (i > 0)
				i--;
			else
				break;
		}
	}
	cout << endl << "</set>" << endl;
#endif
}

static void addCounters (char *ctr, vector<string> & counters)
{
	string s_ctr (ctr);

	size_t position = s_ctr.find (',');
	while (string::npos != position)
	{
		counters.push_back (s_ctr.substr (0, position));
		s_ctr = s_ctr.substr (position+1);
		position  = s_ctr.find (',');
	}
	counters.push_back (s_ctr);
}

static unsigned dumpEventCtrInfo (const char *ctr)
{
	PAPI_event_info_t info;
	int Event;
	int rc;
	char EventName[PAPI_MAX_STR_LEN];

	rc = PAPI_event_name_to_code ((char*)ctr, &Event);
	if (rc != PAPI_OK)
	{
		cout << "Warning! Counter '" << ctr << "' is not available" << endl;
		return 0;
	}

	/* Get the event name */
	rc = PAPI_event_code_to_name (Event, EventName);
	if (rc != PAPI_OK)
		strcpy (EventName, "unknown");

	/* Get event info,
	   native counters can have info.count == 0 */
	rc = PAPI_get_event_info (Event, &info);
	if (rc != PAPI_OK)
	{
		cout << "Warning! Counter '" << ctr << "' is not available" << endl;
		return 0;
	}
	else if (info.count == 0 && (Event & PAPI_NATIVE_MASK) == 0)
	{
		cout << "Warning! Counter '" << ctr << "' is not available" << endl;
		return 0;
	}
	else
	{
		cout << "Counter " << ctr << " (code " << std::hex << Event << std::dec << "): ";
		if (Event&PAPI_NATIVE_MASK)
			cout << "native";
		else
			cout << "derived";
		if (!(Event&PAPI_NATIVE_MASK))
			cout << " (depends on " << info.count << " native counters)";
		cout << endl;
	}
	return 1;
}

int main (int argc, char *argv[])
{
	int rc;
	int i;
	vector<string> omnipresentCounters_tmp, Counters_tmp;

	if (argc < 2)
	{
		cerr << "Usage for " << basename (argv[0]) << endl << endl
		     << "{omnipresent ctr}          ensures that ctr appears in every resulting group" << endl
		     << "{omnipresent ctr1,..,ctrN} ensures that ctr1-ctrN appear in every resulting group" << endl
			 << "ctr                        requests that ctr appears in 1 resulting group" << endl
			 << "ctr1,..,ctrN               requests that ctr1-ctrN appear in 1 resultign group" << endl;

		return -1;
	}

	rc = PAPI_library_init(PAPI_VER_CURRENT);
	if (rc != PAPI_VER_CURRENT && rc > 0)
	{
		cerr << "Error: PAPI library version mismatch!" << endl;
		return -2;
	}

	cout << "This binary was built using PAPI found in " << PAPI_HOME << endl;

	i = 1;
	while (i < argc)
	{
		string param = argv[i];

		if (param == "omnipresent")
		{
			i++;
			if (i < argc)
				addCounters (argv[i], omnipresentCounters_tmp);
		}
		else
			addCounters (argv[i], Counters_tmp);

		i++;
	}

	if (omnipresentCounters.size() >= 8)
	{
		cerr << "Sorry, Extrae is limited to 8 performance counters and you have requested " << omnipresentCounters.size() << " omnipresent counters..." << endl;
		exit (-1);
	}

	vector<string>::iterator it;
	unsigned num_events = 0;
	cout << endl << "** Checking the following omnipresent counters:" << endl;
	for (it = omnipresentCounters_tmp.begin(); it != omnipresentCounters_tmp.end(); it++)
		if (dumpEventCtrInfo ((*it).c_str()))
		{
			omnipresentCounters.push_back (*it);
			num_events++;
		}
	cout << endl << "** Checking the following counters:" << endl;
	for (it = Counters_tmp.begin(); it != Counters_tmp.end(); it++)
		if (dumpEventCtrInfo ((*it).c_str()))
		{
			Counters.push_back (*it);
			num_events++;
		}

	if (num_events == 0)
	{
		cout << endl <<
		     "Sorry, no hardware counters were given or the given are not available." << endl <<
		     "Check " << PAPI_HOME << "/bin/papi_avail or" << endl <<
		     "      " << PAPI_HOME << "/bin/papi_native_avail" << endl <<
		     "to get a list from the available counters in the system." << endl;
		exit (-2);
	}
	else if (num_events >= 64)
	{
		cerr << endl <<
		  "Sorry, we cannot handle 64 or more performance counters at this moment." << endl;
		exit (-3);
	}

	cout << endl;

	size_t ncounters, prevncounters = Counters.size();
	unsigned neventset = 1;
	do
	{
		CheckMaxEventSet (neventset++, omnipresentCounters, Counters);
		ncounters = Counters.size();

		if (prevncounters == ncounters && prevncounters > 0)
		{
			cout << endl <<
			  "Caution, for some reason the following hardware counters cannot be added in an eventset." << endl;
			for (size_t s = 0; s < Counters.size(); s++)
				cout << Counters[i] << " ";
			cout << endl;
			break;
		}
		else
			prevncounters = ncounters;

	} while (Counters.size() > 0);

	return 0;
}

<|endoftext|>


<commit_before>/*  Copyright (c) 2016 Michael Hansen

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE. */

#include "st_string.h"

#include <cstdlib>
#include <cstring>

int ST::string::to_int(int base) const noexcept
{
    return static_cast<int>(strtol(c_str(), nullptr, base));
}

int ST::string::to_int(ST::conversion_result &result, int base) const noexcept
{
    if (empty()) {
        result.m_flags = ST::conversion_result::result_full_match;
        return 0;
    }

    char *end;
    int value = static_cast<int>(strtol(c_str(), &end, base));
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags |= ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

unsigned int ST::string::to_uint(int base) const noexcept
{
    return static_cast<unsigned int>(strtoul(c_str(), nullptr, base));
}

unsigned int ST::string::to_uint(ST::conversion_result &result, int base)
    const noexcept
{
    if (empty()) {
        result.m_flags = ST::conversion_result::result_full_match;
        return 0;
    }

    char *end;
    unsigned int value = static_cast<unsigned int>(strtoul(c_str(), &end, base));
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags |= ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

float ST::string::to_float() const noexcept
{
    return static_cast<float>(strtof(c_str(), nullptr));
}

float ST::string::to_float(ST::conversion_result &result) const noexcept
{
    if (empty()) {
        result.m_flags = ST::conversion_result::result_full_match;
        return 0;
    }

    char *end;
    float value = strtof(c_str(), &end);
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags |= ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

double ST::string::to_double() const noexcept
{
    return strtod(c_str(), nullptr);
}

double ST::string::to_double(ST::conversion_result &result) const noexcept
{
    if (empty()) {
        result.m_flags = ST::conversion_result::result_full_match;
        return 0;
    }

    char *end;
    double value = strtod(c_str(), &end);
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags |= ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

#ifdef ST_HAVE_INT64
int64_t ST::string::to_int64(int base) const noexcept
{
    return static_cast<int64_t>(strtoll(c_str(), nullptr, base));
}

int64_t ST::string::to_int64(ST::conversion_result &result, int base)
    const noexcept
{
    char *end;
    int64_t value = static_cast<int64_t>(strtoll(c_str(), &end, base));
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags = ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

uint64_t ST::string::to_uint64(int base) const noexcept
{
    return static_cast<uint64_t>(strtoull(c_str(), nullptr, base));
}

uint64_t ST::string::to_uint64(ST::conversion_result &result, int base)
    const noexcept
{
    char *end;
    uint64_t value = static_cast<uint64_t>(strtoull(c_str(), &end, base));
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags = ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}
#endif

static int _compare_cs(const char *left, const char *right, size_t fsize) noexcept
{
    return std::char_traits<char>::compare(left, right, fsize);
}

static int _compare_cs(const char *left, size_t lsize,
                       const char *right, size_t rsize) noexcept
{
    return ST::char_buffer::compare(left, lsize, right, rsize);
}

static int _compare_cs(const char *left, size_t lsize,
                       const char *right, size_t rsize, size_t maxlen) noexcept
{
    return ST::char_buffer::compare(left, lsize, right, rsize, maxlen);
}

static int _compare_ci(const char *left, const char *right, size_t fsize) noexcept
{
    while (fsize--) {
        const char cl = _ST_PRIVATE::cl_fast_lower(*left++);
        const char cr = _ST_PRIVATE::cl_fast_lower(*right++);
        if (cl != cr)
            return cl - cr;
    }
    return 0;
}

static int _compare_ci(const char *left, size_t lsize,
                       const char *right, size_t rsize) noexcept
{
    const size_t cmplen = std::min(lsize, rsize);
    const int cmp = _compare_ci(left, right, cmplen);
    return cmp ? cmp : lsize - rsize;
}

static int _compare_ci(const char *left, size_t lsize,
                       const char *right, size_t rsize, size_t maxlen) noexcept
{
    lsize = std::min(lsize, maxlen);
    rsize = std::min(rsize, maxlen);
    return _compare_ci(left, lsize, right, rsize);
}

int ST::string::compare(const string &str, case_sensitivity_t cs) const noexcept
{
    return (cs == case_sensitive) ? _compare_cs(c_str(), size(), str.c_str(), str.size())
                                  : _compare_ci(c_str(), size(), str.c_str(), str.size());
}

int ST::string::compare(const char *str, case_sensitivity_t cs) const noexcept
{
    const size_t rsize = str ? std::char_traits<char>::length(str) : 0;
    return (cs == case_sensitive) ? _compare_cs(c_str(), size(), str ? str : "", rsize)
                                  : _compare_ci(c_str(), size(), str ? str : "", rsize);
}

int ST::string::compare_n(const string &str, size_t count,
                          case_sensitivity_t cs) const noexcept
{
    return (cs == case_sensitive) ? _compare_cs(c_str(), size(), str.c_str(), str.size(), count)
                                  : _compare_ci(c_str(), size(), str.c_str(), str.size(), count);
}

int ST::string::compare_n(const char *str, size_t count,
                          case_sensitivity_t cs) const noexcept
{
    const size_t rsize = str ? std::char_traits<char>::length(str) : 0;
    return (cs == case_sensitive) ? _compare_cs(c_str(), size(), str ? str : "", rsize, count)
                                  : _compare_ci(c_str(), size(), str ? str : "", rsize, count);
}

const char *_ST_PRIVATE::find_cs(const char *haystack, const char *needle)
{
    return strstr(haystack, needle);
}

const char *_ST_PRIVATE::find_ci(const char *haystack, const char *needle)
{
    // The "easy" way
    size_t sublen = std::char_traits<char>::length(needle);
    const char *cp = haystack;
    const char *ep = cp + std::char_traits<char>::length(haystack);
    while (cp + sublen <= ep) {
        if (_compare_ci(cp, needle, sublen) == 0)
            return cp;
        ++cp;
    }
    return nullptr;
}

const char *_ST_PRIVATE::find_ci(const char *haystack, size_t size, char ch)
{
    const char *cp = haystack;
    const char *ep = haystack + size;
    const int lch = _ST_PRIVATE::cl_fast_lower(static_cast<char>(ch));
    while (cp < ep) {
        if (_ST_PRIVATE::cl_fast_lower(*cp) == lch)
            return cp;
        ++cp;
    }
    return nullptr;
}

ST_ssize_t ST::string::find(size_t start, char ch, case_sensitivity_t cs)
    const noexcept
{
    if (start >= size())
        return -1;

    const char *cp = (cs == case_sensitive)
            ? _ST_PRIVATE::find_cs(c_str() + start, size() - start, ch)
            : _ST_PRIVATE::find_ci(c_str() + start, size() - start, ch);
    return cp ? (cp - c_str()) : -1;
}

ST_ssize_t ST::string::find(size_t start, const char *substr, case_sensitivity_t cs)
    const noexcept
{
    if (!substr || !substr[0] || start >= size())
        return -1;

    const char *cp = (cs == case_sensitive)
            ? _ST_PRIVATE::find_cs(c_str() + start, substr)
            : _ST_PRIVATE::find_ci(c_str() + start, substr);
    return cp ? (cp - c_str()) : -1;
}

ST_ssize_t ST::string::find_last(size_t max, char ch, case_sensitivity_t cs) const noexcept
{
    if (empty())
        return -1;

    const char *endp = c_str() + (max > size() ? size() : max);

    const char *start = c_str();
    const char *found = nullptr;
    for ( ;; ) {
        const char *cp = (cs == case_sensitive)
                ? _ST_PRIVATE::find_cs(start, endp - start, ch)
                : _ST_PRIVATE::find_ci(start, endp - start, ch);
        if (!cp || cp >= endp)
            break;
        found = cp;
        start = cp + 1;
    }
    return found ? (found - c_str()) : -1;
}

ST_ssize_t ST::string::find_last(size_t max, const char *substr, case_sensitivity_t cs)
    const noexcept
{
    if (!substr || !substr[0] || empty())
        return -1;

    const char *endp = c_str() + (max > size() ? size() : max);

    const char *start = c_str();
    const char *found = nullptr;
    for ( ;; ) {
        const char *cp = (cs == case_sensitive)
                ? _ST_PRIVATE::find_cs(start, substr)
                : _ST_PRIVATE::find_ci(start, substr);
        if (!cp || cp >= endp)
            break;
        found = cp;
        start = cp + 1;
    }
    return found ? (found - c_str()) : -1;
}

bool ST::string::starts_with(const ST::string &prefix, case_sensitivity_t cs) const noexcept
{
    if (prefix.size() > size())
        return false;
    return compare_n(prefix, prefix.size(), cs) == 0;
}

bool ST::string::starts_with(const char *prefix, case_sensitivity_t cs) const noexcept
{
    size_t count = prefix ? std::char_traits<char>::length(prefix) : 0;
    if (count > size())
        return false;
    return compare_n(prefix, count, cs) == 0;
}

bool ST::string::ends_with(const ST::string &suffix, case_sensitivity_t cs) const noexcept
{
    if (suffix.size() > size())
        return false;

    size_t start = size() - suffix.size();
    return (cs == case_sensitive)
            ? _compare_cs(c_str() + start, suffix.c_str(), suffix.size()) == 0
            : _compare_ci(c_str() + start, suffix.c_str(), suffix.size()) == 0;
}

bool ST::string::ends_with(const char *suffix, case_sensitivity_t cs) const noexcept
{
    size_t count = suffix ? std::char_traits<char>::length(suffix) : 0;
    if (count > size())
        return false;

    size_t start = size() - count;
    return (cs == case_sensitive)
            ? _compare_cs(c_str() + start, suffix ? suffix : "", count) == 0
            : _compare_ci(c_str() + start, suffix ? suffix : "", count) == 0;
}

template <size_t Size>
struct _fnv_constants { };

template <>
struct _fnv_constants<4>
{
    static constexpr size_t offset_basis = 0x811c9dc5UL;
    static constexpr size_t prime = 0x01000193UL;
};

template<>
struct _fnv_constants<8>
{
    static constexpr size_t offset_basis = 0xcbf29ce484222325ULL;
    static constexpr size_t prime = 0x00000100000001b3ULL;
};

typedef _fnv_constants<sizeof(size_t)> fnv_constants;

size_t ST::hash::operator()(const string &str) const noexcept
{
    /* FNV-1a hash.  See http://isthe.com/chongo/tech/comp/fnv/ for details */
    size_t hash = fnv_constants::offset_basis;
    const char *cp = str.c_str();
    const char *ep = cp + str.size();
    while (cp < ep) {
        hash ^= static_cast<size_t>(*cp++);
        hash *= fnv_constants::prime;
    }
    return hash;
}

size_t ST::hash_i::operator()(const string &str) const noexcept
{
    /* FNV-1a hash.  See http://isthe.com/chongo/tech/comp/fnv/ for details */
    size_t hash = fnv_constants::offset_basis;
    const char *cp = str.c_str();
    const char *ep = cp + str.size();
    while (cp < ep) {
        hash ^= static_cast<size_t>(_ST_PRIVATE::cl_fast_lower(*cp++));
        hash *= fnv_constants::prime;
    }
    return hash;
}
<commit_msg>Avoid -Woverflow warnings when compiling on 32-bit size_t architectures.<commit_after>/*  Copyright (c) 2016 Michael Hansen

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE. */

#include "st_string.h"

#include <cstdlib>
#include <cstring>

int ST::string::to_int(int base) const noexcept
{
    return static_cast<int>(strtol(c_str(), nullptr, base));
}

int ST::string::to_int(ST::conversion_result &result, int base) const noexcept
{
    if (empty()) {
        result.m_flags = ST::conversion_result::result_full_match;
        return 0;
    }

    char *end;
    int value = static_cast<int>(strtol(c_str(), &end, base));
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags |= ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

unsigned int ST::string::to_uint(int base) const noexcept
{
    return static_cast<unsigned int>(strtoul(c_str(), nullptr, base));
}

unsigned int ST::string::to_uint(ST::conversion_result &result, int base)
    const noexcept
{
    if (empty()) {
        result.m_flags = ST::conversion_result::result_full_match;
        return 0;
    }

    char *end;
    unsigned int value = static_cast<unsigned int>(strtoul(c_str(), &end, base));
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags |= ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

float ST::string::to_float() const noexcept
{
    return static_cast<float>(strtof(c_str(), nullptr));
}

float ST::string::to_float(ST::conversion_result &result) const noexcept
{
    if (empty()) {
        result.m_flags = ST::conversion_result::result_full_match;
        return 0;
    }

    char *end;
    float value = strtof(c_str(), &end);
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags |= ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

double ST::string::to_double() const noexcept
{
    return strtod(c_str(), nullptr);
}

double ST::string::to_double(ST::conversion_result &result) const noexcept
{
    if (empty()) {
        result.m_flags = ST::conversion_result::result_full_match;
        return 0;
    }

    char *end;
    double value = strtod(c_str(), &end);
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags |= ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

#ifdef ST_HAVE_INT64
int64_t ST::string::to_int64(int base) const noexcept
{
    return static_cast<int64_t>(strtoll(c_str(), nullptr, base));
}

int64_t ST::string::to_int64(ST::conversion_result &result, int base)
    const noexcept
{
    char *end;
    int64_t value = static_cast<int64_t>(strtoll(c_str(), &end, base));
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags = ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}

uint64_t ST::string::to_uint64(int base) const noexcept
{
    return static_cast<uint64_t>(strtoull(c_str(), nullptr, base));
}

uint64_t ST::string::to_uint64(ST::conversion_result &result, int base)
    const noexcept
{
    char *end;
    uint64_t value = static_cast<uint64_t>(strtoull(c_str(), &end, base));
    result.m_flags = 0;
    if (end != c_str())
        result.m_flags = ST::conversion_result::result_ok;
    if (end == c_str() + size())
        result.m_flags |= ST::conversion_result::result_full_match;
    return value;
}
#endif

static int _compare_cs(const char *left, const char *right, size_t fsize) noexcept
{
    return std::char_traits<char>::compare(left, right, fsize);
}

static int _compare_cs(const char *left, size_t lsize,
                       const char *right, size_t rsize) noexcept
{
    return ST::char_buffer::compare(left, lsize, right, rsize);
}

static int _compare_cs(const char *left, size_t lsize,
                       const char *right, size_t rsize, size_t maxlen) noexcept
{
    return ST::char_buffer::compare(left, lsize, right, rsize, maxlen);
}

static int _compare_ci(const char *left, const char *right, size_t fsize) noexcept
{
    while (fsize--) {
        const char cl = _ST_PRIVATE::cl_fast_lower(*left++);
        const char cr = _ST_PRIVATE::cl_fast_lower(*right++);
        if (cl != cr)
            return cl - cr;
    }
    return 0;
}

static int _compare_ci(const char *left, size_t lsize,
                       const char *right, size_t rsize) noexcept
{
    const size_t cmplen = std::min(lsize, rsize);
    const int cmp = _compare_ci(left, right, cmplen);
    return cmp ? cmp : lsize - rsize;
}

static int _compare_ci(const char *left, size_t lsize,
                       const char *right, size_t rsize, size_t maxlen) noexcept
{
    lsize = std::min(lsize, maxlen);
    rsize = std::min(rsize, maxlen);
    return _compare_ci(left, lsize, right, rsize);
}

int ST::string::compare(const string &str, case_sensitivity_t cs) const noexcept
{
    return (cs == case_sensitive) ? _compare_cs(c_str(), size(), str.c_str(), str.size())
                                  : _compare_ci(c_str(), size(), str.c_str(), str.size());
}

int ST::string::compare(const char *str, case_sensitivity_t cs) const noexcept
{
    const size_t rsize = str ? std::char_traits<char>::length(str) : 0;
    return (cs == case_sensitive) ? _compare_cs(c_str(), size(), str ? str : "", rsize)
                                  : _compare_ci(c_str(), size(), str ? str : "", rsize);
}

int ST::string::compare_n(const string &str, size_t count,
                          case_sensitivity_t cs) const noexcept
{
    return (cs == case_sensitive) ? _compare_cs(c_str(), size(), str.c_str(), str.size(), count)
                                  : _compare_ci(c_str(), size(), str.c_str(), str.size(), count);
}

int ST::string::compare_n(const char *str, size_t count,
                          case_sensitivity_t cs) const noexcept
{
    const size_t rsize = str ? std::char_traits<char>::length(str) : 0;
    return (cs == case_sensitive) ? _compare_cs(c_str(), size(), str ? str : "", rsize, count)
                                  : _compare_ci(c_str(), size(), str ? str : "", rsize, count);
}

const char *_ST_PRIVATE::find_cs(const char *haystack, const char *needle)
{
    return strstr(haystack, needle);
}

const char *_ST_PRIVATE::find_ci(const char *haystack, const char *needle)
{
    // The "easy" way
    size_t sublen = std::char_traits<char>::length(needle);
    const char *cp = haystack;
    const char *ep = cp + std::char_traits<char>::length(haystack);
    while (cp + sublen <= ep) {
        if (_compare_ci(cp, needle, sublen) == 0)
            return cp;
        ++cp;
    }
    return nullptr;
}

const char *_ST_PRIVATE::find_ci(const char *haystack, size_t size, char ch)
{
    const char *cp = haystack;
    const char *ep = haystack + size;
    const int lch = _ST_PRIVATE::cl_fast_lower(static_cast<char>(ch));
    while (cp < ep) {
        if (_ST_PRIVATE::cl_fast_lower(*cp) == lch)
            return cp;
        ++cp;
    }
    return nullptr;
}

ST_ssize_t ST::string::find(size_t start, char ch, case_sensitivity_t cs)
    const noexcept
{
    if (start >= size())
        return -1;

    const char *cp = (cs == case_sensitive)
            ? _ST_PRIVATE::find_cs(c_str() + start, size() - start, ch)
            : _ST_PRIVATE::find_ci(c_str() + start, size() - start, ch);
    return cp ? (cp - c_str()) : -1;
}

ST_ssize_t ST::string::find(size_t start, const char *substr, case_sensitivity_t cs)
    const noexcept
{
    if (!substr || !substr[0] || start >= size())
        return -1;

    const char *cp = (cs == case_sensitive)
            ? _ST_PRIVATE::find_cs(c_str() + start, substr)
            : _ST_PRIVATE::find_ci(c_str() + start, substr);
    return cp ? (cp - c_str()) : -1;
}

ST_ssize_t ST::string::find_last(size_t max, char ch, case_sensitivity_t cs) const noexcept
{
    if (empty())
        return -1;

    const char *endp = c_str() + (max > size() ? size() : max);

    const char *start = c_str();
    const char *found = nullptr;
    for ( ;; ) {
        const char *cp = (cs == case_sensitive)
                ? _ST_PRIVATE::find_cs(start, endp - start, ch)
                : _ST_PRIVATE::find_ci(start, endp - start, ch);
        if (!cp || cp >= endp)
            break;
        found = cp;
        start = cp + 1;
    }
    return found ? (found - c_str()) : -1;
}

ST_ssize_t ST::string::find_last(size_t max, const char *substr, case_sensitivity_t cs)
    const noexcept
{
    if (!substr || !substr[0] || empty())
        return -1;

    const char *endp = c_str() + (max > size() ? size() : max);

    const char *start = c_str();
    const char *found = nullptr;
    for ( ;; ) {
        const char *cp = (cs == case_sensitive)
                ? _ST_PRIVATE::find_cs(start, substr)
                : _ST_PRIVATE::find_ci(start, substr);
        if (!cp || cp >= endp)
            break;
        found = cp;
        start = cp + 1;
    }
    return found ? (found - c_str()) : -1;
}

bool ST::string::starts_with(const ST::string &prefix, case_sensitivity_t cs) const noexcept
{
    if (prefix.size() > size())
        return false;
    return compare_n(prefix, prefix.size(), cs) == 0;
}

bool ST::string::starts_with(const char *prefix, case_sensitivity_t cs) const noexcept
{
    size_t count = prefix ? std::char_traits<char>::length(prefix) : 0;
    if (count > size())
        return false;
    return compare_n(prefix, count, cs) == 0;
}

bool ST::string::ends_with(const ST::string &suffix, case_sensitivity_t cs) const noexcept
{
    if (suffix.size() > size())
        return false;

    size_t start = size() - suffix.size();
    return (cs == case_sensitive)
            ? _compare_cs(c_str() + start, suffix.c_str(), suffix.size()) == 0
            : _compare_ci(c_str() + start, suffix.c_str(), suffix.size()) == 0;
}

bool ST::string::ends_with(const char *suffix, case_sensitivity_t cs) const noexcept
{
    size_t count = suffix ? std::char_traits<char>::length(suffix) : 0;
    if (count > size())
        return false;

    size_t start = size() - count;
    return (cs == case_sensitive)
            ? _compare_cs(c_str() + start, suffix ? suffix : "", count) == 0
            : _compare_ci(c_str() + start, suffix ? suffix : "", count) == 0;
}

template <typename SizeType, size_t Size = sizeof(SizeType)>
struct _fnv_constants { };

template <typename SizeType>
struct _fnv_constants<SizeType, 4>
{
    static constexpr SizeType offset_basis = 0x811c9dc5UL;
    static constexpr SizeType prime = 0x01000193UL;
};

template <typename SizeType>
struct _fnv_constants<SizeType, 8>
{
    static constexpr SizeType offset_basis = 0xcbf29ce484222325ULL;
    static constexpr SizeType prime = 0x00000100000001b3ULL;
};

typedef _fnv_constants<size_t> fnv_constants;

size_t ST::hash::operator()(const string &str) const noexcept
{
    /* FNV-1a hash.  See http://isthe.com/chongo/tech/comp/fnv/ for details */
    size_t hash = fnv_constants::offset_basis;
    const char *cp = str.c_str();
    const char *ep = cp + str.size();
    while (cp < ep) {
        hash ^= static_cast<size_t>(*cp++);
        hash *= fnv_constants::prime;
    }
    return hash;
}

size_t ST::hash_i::operator()(const string &str) const noexcept
{
    /* FNV-1a hash.  See http://isthe.com/chongo/tech/comp/fnv/ for details */
    size_t hash = fnv_constants::offset_basis;
    const char *cp = str.c_str();
    const char *ep = cp + str.size();
    while (cp < ep) {
        hash ^= static_cast<size_t>(_ST_PRIVATE::cl_fast_lower(*cp++));
        hash *= fnv_constants::prime;
    }
    return hash;
}
<|endoftext|>


<commit_before>/*******************************************************************************
*    ALMA - Atacama Large Millimiter Array
*    (c) Associated Universities Inc., 2002 *
*    (c) European Southern Observatory, 2002
*    Copyright by ESO (in the framework of the ALMA collaboration)
*    and Cosylab 2002, All rights reserved
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation; either
*    version 2.1 of the License, or (at your option) any later version.
*
*    This library 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
*    Lesser General Public License for more details.
*
*    You should have received a copy of the GNU Lesser General Public
*    License along with this library; if not, write to the Free Software
*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*
*
*
* "@(#) $Id: contLogTestImpl.cpp,v 1.12 2008/01/30 11:08:07 eallaert Exp $"
*
* who       when        what
* --------  ----------  ----------------------------------------------
* eallaert  2007-11-05  initial version
*
*/

#include <contLogTestImpl.h>
#include <ACSErrTypeCommon.h>
#include <loggingLogLevelDefinition.h>
#include <loggingLogger.h>
#include "loggingGetLogger.h"
#include <iostream>

ACE_RCSID(contLogTest, contLogTestImpl, "$Id: contLogTestImpl.cpp,v 1.12 2008/01/30 11:08:07 eallaert Exp $")

/* ----------------------------------------------------------------*/
TestLogLevelsComp::TestLogLevelsComp(
		       const ACE_CString &name,
		       maci::ContainerServices * containerServices) :
    ACSComponentImpl(name, containerServices)
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::TestLogLevelsComp::TestLogLevelsComp");
}
/* ----------------------------------------------------------------*/
TestLogLevelsComp::~TestLogLevelsComp()
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::TestLogLevelsComp::~TestLogLevelsComp");
    ACS_DEBUG_PARAM("::TestLogLevelsComp::~TestLogLevelsComp", "Destroying %s...", name());
}
/* --------------------- [ CORBA interface ] ----------------------*/
::contLogTest::LongSeq*
TestLogLevelsComp::getLevels ()
    throw (CORBA::SystemException, ACSErrTypeCommon::CouldntPerformActionEx)
{
    Logging::Logger *l = getLogger();
    ::contLogTest::LongSeq_var level = new ::contLogTest::LongSeq(5);
	level->length(5);

    // need a way to retrieve default/hardcoded settings, i.e. the
    // equivalent of Java's logConfig.getMinLogLevel() etc. in C++.
	// Hardcode these values for the time being ;-)
	level[0] = static_cast< CORBA::Long >(2);
	level[1] = static_cast< CORBA::Long >(2);

    level[3] = static_cast< CORBA::Long >(LogLevelDefinition::fromACEPriority(ACE_Log_Priority(l->getRemoteLevel())));
    level[4] = static_cast< CORBA::Long >(LogLevelDefinition::fromACEPriority(ACE_Log_Priority(l->getLocalLevel())));

    level[2] = (level[3] < level[4] ? level[3] : level[4]);

    return level._retn();
}

void
TestLogLevelsComp::logDummyMessages (const ::contLogTest::LongSeq & levels)
{
	ACE_Log_Priority p;
	CORBA::ULong t=0;
	for (t=0; t<levels.length(); t++){
		p = LogLevelDefinition::getACELogPriority(levels[t]);
		LogLevelDefinition lld = LogLevelDefinition::fromInteger(levels[t]);
		ACS_SHORT_LOG((p, "dummy log message for core level %d/%s", lld.getValue(), lld.getName().c_str()));
	}
	// log last message always at highest, non-OFF level (so it should get always through,
	// unless the central level is put to OFF).
	p = LogLevelDefinition::getACELogPriority(AcsLogLevels::EMERGENCY_VAL);
	ACS_SHORT_LOG((p, "===last log message==="));

	// Note that these tests may be running in a container with default
	// settings, i.e. whereby " immediateDispatchLevel" can be anything,
	// and dispatchPacketSize as well. Empirically, in such case,
	// C++ seems to sends logs in packets of 5 logs, so add 4 messages to
	// ensure all the above logs get sent across right now.
	for (int i = 0; i < 4; i++) {
		ACS_SHORT_LOG((p, "===packet fill-up message==="));
	}

}

/* --------------- [ MACI DLL support functions ] -----------------*/
#include <maciACSComponentDefines.h>
MACI_DLL_SUPPORT_FUNCTIONS(TestLogLevelsComp)
/* ----------------------------------------------------------------*/

/*___oOo___*/

<commit_msg>Sleep 250 ms before starting to send logs.<commit_after>/*******************************************************************************
*    ALMA - Atacama Large Millimiter Array
*    (c) Associated Universities Inc., 2002 *
*    (c) European Southern Observatory, 2002
*    Copyright by ESO (in the framework of the ALMA collaboration)
*    and Cosylab 2002, All rights reserved
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation; either
*    version 2.1 of the License, or (at your option) any later version.
*
*    This library 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
*    Lesser General Public License for more details.
*
*    You should have received a copy of the GNU Lesser General Public
*    License along with this library; if not, write to the Free Software
*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*
*
*
* "@(#) $Id: contLogTestImpl.cpp,v 1.13 2008/06/24 13:45:46 eallaert Exp $"
*
* who       when        what
* --------  ----------  ----------------------------------------------
* eallaert  2007-11-05  initial version
*
*/

#include <contLogTestImpl.h>
#include <ACSErrTypeCommon.h>
#include <loggingLogLevelDefinition.h>
#include <loggingLogger.h>
#include "loggingGetLogger.h"
#include <iostream>

ACE_RCSID(contLogTest, contLogTestImpl, "$Id: contLogTestImpl.cpp,v 1.13 2008/06/24 13:45:46 eallaert Exp $")

/* ----------------------------------------------------------------*/
TestLogLevelsComp::TestLogLevelsComp(
		       const ACE_CString &name,
		       maci::ContainerServices * containerServices) :
    ACSComponentImpl(name, containerServices)
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::TestLogLevelsComp::TestLogLevelsComp");
}
/* ----------------------------------------------------------------*/
TestLogLevelsComp::~TestLogLevelsComp()
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::TestLogLevelsComp::~TestLogLevelsComp");
    ACS_DEBUG_PARAM("::TestLogLevelsComp::~TestLogLevelsComp", "Destroying %s...", name());
}
/* --------------------- [ CORBA interface ] ----------------------*/
::contLogTest::LongSeq*
TestLogLevelsComp::getLevels ()
    throw (CORBA::SystemException, ACSErrTypeCommon::CouldntPerformActionEx)
{
    Logging::Logger *l = getLogger();
    ::contLogTest::LongSeq_var level = new ::contLogTest::LongSeq(5);
	level->length(5);

    // need a way to retrieve default/hardcoded settings, i.e. the
    // equivalent of Java's logConfig.getMinLogLevel() etc. in C++.
	// Hardcode these values for the time being ;-)
	level[0] = static_cast< CORBA::Long >(2);
	level[1] = static_cast< CORBA::Long >(2);

    level[3] = static_cast< CORBA::Long >(LogLevelDefinition::fromACEPriority(ACE_Log_Priority(l->getRemoteLevel())));
    level[4] = static_cast< CORBA::Long >(LogLevelDefinition::fromACEPriority(ACE_Log_Priority(l->getLocalLevel())));

    level[2] = (level[3] < level[4] ? level[3] : level[4]);

    return level._retn();
}

void
TestLogLevelsComp::logDummyMessages (const ::contLogTest::LongSeq & levels)
{
	ACE_Log_Priority p;
	CORBA::ULong t=0;
	// Give client time to start waiting for logs
	usleep(250000);
	for (t=0; t<levels.length(); t++){
		p = LogLevelDefinition::getACELogPriority(levels[t]);
		LogLevelDefinition lld = LogLevelDefinition::fromInteger(levels[t]);
		ACS_SHORT_LOG((p, "dummy log message for core level %d/%s", lld.getValue(), lld.getName().c_str()));
	}
	// log last message always at highest, non-OFF level (so it should get always through,
	// unless the central level is put to OFF).
	p = LogLevelDefinition::getACELogPriority(AcsLogLevels::EMERGENCY_VAL);
	ACS_SHORT_LOG((p, "===last log message==="));

	// Note that these tests may be running in a container with default
	// settings, i.e. whereby " immediateDispatchLevel" can be anything,
	// and dispatchPacketSize as well. Empirically, in such case,
	// C++ seems to sends logs in packets of 5 logs, so add 4 messages to
	// ensure all the above logs get sent across right now.
	for (int i = 0; i < 4; i++) {
		ACS_SHORT_LOG((p, "===packet fill-up message==="));
	}

}

/* --------------- [ MACI DLL support functions ] -----------------*/
#include <maciACSComponentDefines.h>
MACI_DLL_SUPPORT_FUNCTIONS(TestLogLevelsComp)
/* ----------------------------------------------------------------*/

/*___oOo___*/

<|endoftext|>


<commit_before>// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s
template<typename T> struct Identity {
  typedef T Type;
};

void f(Identity<int>::Type a) {}
void f(Identity<int> a) {}
void f(int& a) { }

template<typename T> struct A {
  A<T> *next;
};
void f(A<int>) { }

struct B { };

void f() {
  int B::*a = 0;
  void (B::*b)() = 0;
}

namespace EmptyNameCrash {
  struct A { A(); };
  typedef struct { A x; } B;
  B x;
}

// PR4890
namespace PR4890 {
  struct X {
    ~X();
  };

  X::~X() { }
}

namespace VirtualDtor {
  struct Y {
    virtual ~Y();
  };

  Y::~Y() { }
}

namespace VirtualBase {
  struct A { };
  struct B : virtual A { };

  void f() {
    B b;
  }
}

void foo() {
  const wchar_t c = L'x';
  wchar_t d = c;
}

namespace b5249287 {
template <typename T> class A {
  struct B;
};

class Cls {
  template <typename T> friend class A<T>::B;
};

Cls obj;
}

namespace pr14763 {
struct foo {
  foo(const foo&);
};

foo func(foo f) {
  return f; // reference 'f' for now because otherwise we hit another bug
}

// CHECK: [[FUNC:![0-9]*]] = {{.*}} metadata !"_ZN7pr147634funcENS_3fooE", i32 {{[0-9]*}}, metadata [[FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func]
// CHECK: [[PR14763:![0-9]*]] = {{.*}} ; [ DW_TAG_namespace ] [pr14763]
// CHECK: [[FOO:![0-9]*]] = metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata [[PR14763]], {{.*}} ; [ DW_TAG_structure_type ] [foo]
}

namespace pr9608 { // also pr9600
struct incomplete;
incomplete (*x)[3];
// CHECK: metadata [[INCARRAYPTR:![0-9]*]], i32 0, i32 1, [3 x i8]** @_ZN6pr96081xE, null} ; [ DW_TAG_variable ] [x]
// CHECK: [[INCARRAYPTR]] = {{.*}}metadata [[INCARRAY:![0-9]*]]} ; [ DW_TAG_pointer_type ]
// CHECK: [[INCARRAY]] = {{.*}}metadata [[INCTYPE:![0-9]*]], metadata {{![0-9]*}}, i32 0, i32 0} ; [ DW_TAG_array_type ] [line 0, size 0, align 0, offset 0] [from incomplete]
// CHECK: [[INCTYPE]] = {{.*}} ; [ DW_TAG_structure_type ] [incomplete]{{.*}} [fwd]
}

// For some reason the argument for PR14763 ended up all the way down here
// CHECK: = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], {{.*}}, metadata [[FOO]], i32 8192, i32 0} ; [ DW_TAG_arg_variable ] [f]

namespace pr16214 {
struct a {
  int i;
};

typedef a at;

struct b {
};

typedef b bt;

void func() {
  at a_inst;
  bt *b_ptr_inst;
  const bt *b_cnst_ptr_inst;
}

// CHECK: metadata [[A_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [a]
// CHECK: [[A_MEM]] = metadata !{metadata [[A_I:![0-9]*]], metadata !{{[0-9]*}}}
// CHECK: [[A_I]] = {{.*}} ; [ DW_TAG_member ] [i] {{.*}} [from int]
// CHECK: ; [ DW_TAG_structure_type ] [b] {{.*}}[fwd]
}
<commit_msg>Fix CodeGenCXX/debug-info.cpp test on Windows<commit_after>// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s
template<typename T> struct Identity {
  typedef T Type;
};

void f(Identity<int>::Type a) {}
void f(Identity<int> a) {}
void f(int& a) { }

template<typename T> struct A {
  A<T> *next;
};
void f(A<int>) { }

struct B { };

void f() {
  int B::*a = 0;
  void (B::*b)() = 0;
}

namespace EmptyNameCrash {
  struct A { A(); };
  typedef struct { A x; } B;
  B x;
}

// PR4890
namespace PR4890 {
  struct X {
    ~X();
  };

  X::~X() { }
}

namespace VirtualDtor {
  struct Y {
    virtual ~Y();
  };

  Y::~Y() { }
}

namespace VirtualBase {
  struct A { };
  struct B : virtual A { };

  void f() {
    B b;
  }
}

void foo() {
  const wchar_t c = L'x';
  wchar_t d = c;
}

namespace b5249287 {
template <typename T> class A {
  struct B;
};

class Cls {
  template <typename T> friend class A<T>::B;
};

Cls obj;
}

namespace pr14763 {
struct foo {
  foo(const foo&);
};

foo func(foo f) {
  return f; // reference 'f' for now because otherwise we hit another bug
}

// CHECK: [[FUNC:![0-9]*]] = {{.*}} metadata !"_ZN7pr147634funcENS_3fooE", i32 {{[0-9]*}}, metadata [[FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func]
// CHECK: [[PR14763:![0-9]*]] = {{.*}} ; [ DW_TAG_namespace ] [pr14763]
// CHECK: [[FOO:![0-9]*]] = metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata [[PR14763]], {{.*}} ; [ DW_TAG_structure_type ] [foo]
}

namespace pr9608 { // also pr9600
struct incomplete;
incomplete (*x)[3];
// CHECK: metadata [[INCARRAYPTR:![0-9]*]], i32 0, i32 1, [3 x i8]** @_ZN6pr96081xE, null} ; [ DW_TAG_variable ] [x]
// CHECK: [[INCARRAYPTR]] = {{.*}}metadata [[INCARRAY:![0-9]*]]} ; [ DW_TAG_pointer_type ]
// CHECK: [[INCARRAY]] = {{.*}}metadata [[INCTYPE:![0-9]*]], metadata {{![0-9]*}}, i32 0, i32 0} ; [ DW_TAG_array_type ] [line 0, size 0, align 0, offset 0] [from incomplete]
// CHECK: [[INCTYPE]] = {{.*}} ; [ DW_TAG_structure_type ] [incomplete]{{.*}} [fwd]
}

// For some reason the argument for PR14763 ended up all the way down here
// CHECK: = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], {{.*}}, metadata [[FOO]], i32 {{[0-9]+}}, i32 0} ; [ DW_TAG_arg_variable ] [f]

namespace pr16214 {
struct a {
  int i;
};

typedef a at;

struct b {
};

typedef b bt;

void func() {
  at a_inst;
  bt *b_ptr_inst;
  const bt *b_cnst_ptr_inst;
}

// CHECK: metadata [[A_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [a]
// CHECK: [[A_MEM]] = metadata !{metadata [[A_I:![0-9]*]], metadata !{{[0-9]*}}}
// CHECK: [[A_I]] = {{.*}} ; [ DW_TAG_member ] [i] {{.*}} [from int]
// CHECK: ; [ DW_TAG_structure_type ] [b] {{.*}}[fwd]
}
<|endoftext|>