<commit_before>/*
 *  Scriptorium.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Wed 10 Nov 2004.
 *  Copyright (c) 2004-2006 Alyssa Milburn. All rights reserved.
 *  Copyright (c) 2005 Bryan Donlan. 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 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.
 *
 */

#include "Scriptorium.h"
#include <iostream>

inline unsigned int Scriptorium::calculateValue(unsigned char family, unsigned char genus, unsigned short species) {
	return (family + (genus << 8) + (species << 16));
}

void Scriptorium::addScript(unsigned char family, unsigned char genus, unsigned short species, unsigned short event, shared_ptr<script> s) {
	std::map<unsigned short, shared_ptr<script> > &m = getScripts(calculateValue(family, genus, species));
	m[event] = s;
}

void Scriptorium::delScript(unsigned char family, unsigned char genus, unsigned short species, unsigned short event) {
	// Retrieve the list of scripts for the classifier, return if there aren't any.
	std::map<unsigned int, std::map<unsigned short, shared_ptr<script> > >::iterator x = scripts.find(calculateValue(family, genus, species));
	if (x == scripts.end())
		return;

	// Retrieve the script, return if it doesn't exist.
	std::map<unsigned short, shared_ptr<script> >::iterator j = x->second.find(event);
	if (j == x->second.end())
		return;

	// Erase the script.
	x->second.erase(j);

	// If there are no scripts left, erase the whole list of scripts for this classifier.
	if (x->second.size() == 0)
		scripts.erase(x);
}

shared_ptr<script> Scriptorium::getScript(unsigned char family, unsigned char genus, unsigned short species, unsigned short event) {
	std::map<unsigned short, shared_ptr<script> > &x = getScripts(calculateValue(family, genus, species));
	if (x.find(event) == x.end()) {
		std::map<unsigned short, shared_ptr<script> > &x = getScripts(calculateValue(family, genus, 0));
		if (x.find(event) == x.end()) {
			std::map<unsigned short, shared_ptr<script> > &x = getScripts(calculateValue(family, 0, 0));
			if (x.find(event) == x.end())
				return shared_ptr<script>();
			else
				return x[event];
		} else return x[event];
	} else return x[event];
}

/* vim: set noet: */
<commit_msg>Scriptorium: match scripts with family/genus/species of 0/0/0 as a last resort<commit_after>/*
 *  Scriptorium.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Wed 10 Nov 2004.
 *  Copyright (c) 2004-2006 Alyssa Milburn. All rights reserved.
 *  Copyright (c) 2005 Bryan Donlan. 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 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.
 *
 */

#include "Scriptorium.h"
#include <iostream>

inline unsigned int Scriptorium::calculateValue(unsigned char family, unsigned char genus, unsigned short species) {
	return (family + (genus << 8) + (species << 16));
}

void Scriptorium::addScript(unsigned char family, unsigned char genus, unsigned short species, unsigned short event, shared_ptr<script> s) {
	std::map<unsigned short, shared_ptr<script> > &m = getScripts(calculateValue(family, genus, species));
	m[event] = s;
}

void Scriptorium::delScript(unsigned char family, unsigned char genus, unsigned short species, unsigned short event) {
	// Retrieve the list of scripts for the classifier, return if there aren't any.
	std::map<unsigned int, std::map<unsigned short, shared_ptr<script> > >::iterator x = scripts.find(calculateValue(family, genus, species));
	if (x == scripts.end())
		return;

	// Retrieve the script, return if it doesn't exist.
	std::map<unsigned short, shared_ptr<script> >::iterator j = x->second.find(event);
	if (j == x->second.end())
		return;

	// Erase the script.
	x->second.erase(j);

	// If there are no scripts left, erase the whole list of scripts for this classifier.
	if (x->second.size() == 0)
		scripts.erase(x);
}

shared_ptr<script> Scriptorium::getScript(unsigned char family, unsigned char genus, unsigned short species, unsigned short event) {
	std::map<unsigned short, shared_ptr<script> > &x = getScripts(calculateValue(family, genus, species));
	if (x.find(event) == x.end()) {
		std::map<unsigned short, shared_ptr<script> > &x = getScripts(calculateValue(family, genus, 0));
		if (x.find(event) == x.end()) {
			std::map<unsigned short, shared_ptr<script> > &x = getScripts(calculateValue(family, 0, 0));
			if (x.find(event) == x.end()) {
				std::map<unsigned short, shared_ptr<script> > &x = getScripts(calculateValue(0, 0, 0));
				if (x.find(event) == x.end()) {
					return shared_ptr<script>();
				} else return x[event];
			} else return x[event];
		} else return x[event];
	} else return x[event];
}

/* vim: set noet: */
<|endoftext|>


<commit_before>//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This header file implements the operating system DynamicLibrary concept.
//
//===----------------------------------------------------------------------===//

#include "llvm/System/DynamicLibrary.h"
#include "llvm/Config/config.h"
#include <map>

// Collection of symbol name/value pairs to be searched prior to any libraries.
static std::map<std::string, void *> g_symbols;

void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName,
                                          void *symbolValue) {
  g_symbols[symbolName] = symbolValue;
}

// It is not possible to use ltdl.c on VC++ builds as the terms of its LGPL
// license and special exception would cause all of LLVM to be placed under
// the LGPL.  This is because the exception applies only when libtool is
// used, and obviously libtool is not used with Visual Studio.  An entirely
// separate implementation is provided in win32/DynamicLibrary.cpp.

#ifdef LLVM_ON_WIN32

#include "Win32/DynamicLibrary.inc"

#else

#include "ltdl.h"
#include <cassert>
using namespace llvm;
using namespace llvm::sys;

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

static inline void check_ltdl_initialization() {
  static bool did_initialize_ltdl = false;
  if (!did_initialize_ltdl) {
    int Err = lt_dlinit();
    assert(0 == Err && "Can't init the ltdl library");
    did_initialize_ltdl = true;
  }
}

static std::vector<lt_dlhandle> OpenedHandles;

DynamicLibrary::DynamicLibrary() : handle(0) {
  check_ltdl_initialization();

  lt_dlhandle a_handle = lt_dlopen(0);

  assert(a_handle == 0 || "Can't open program as dynamic library");

  handle = a_handle;
  OpenedHandles.push_back(a_handle);
}

/*
DynamicLibrary::DynamicLibrary(const char*filename) : handle(0) {
  check_ltdl_initialization();

  lt_dlhandle a_handle = lt_dlopen(filename);

  if (a_handle == 0)
    a_handle = lt_dlopenext(filename);

  if (a_handle == 0)
    throw std::string("Can't open :") + filename + ": " + lt_dlerror();

  handle = a_handle;
  OpenedHandles.push_back(a_handle);
}
*/

DynamicLibrary::~DynamicLibrary() {
  lt_dlhandle a_handle = (lt_dlhandle) handle;
  if (a_handle) {
    lt_dlclose(a_handle);

    for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(),
         E = OpenedHandles.end(); I != E; ++I) {
      if (*I == a_handle) {
        // Note: don't use the swap/pop_back trick here. Order is important.
        OpenedHandles.erase(I);
        return;
      }
    }
  }
}

bool DynamicLibrary::LoadLibraryPermanently(const char *Filename,
                                            std::string *ErrMsg) {
  check_ltdl_initialization();
  lt_dlhandle a_handle = lt_dlopen(Filename);

  if (a_handle == 0)
    a_handle = lt_dlopenext(Filename);

  if (a_handle == 0) {
    if (ErrMsg)
      *ErrMsg = std::string("Can't open :") +
          (Filename ? Filename : "<current process>") + ": " + lt_dlerror();
    return true;
  }

  lt_dlmakeresident(a_handle);

  OpenedHandles.push_back(a_handle);
  return false;
}

void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
  check_ltdl_initialization();

  // First check symbols added via AddSymbol().
  std::map<std::string, void *>::iterator I = g_symbols.find(symbolName);
  if (I != g_symbols.end())
    return I->second;

  // Now search the libraries.
  for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(),
       E = OpenedHandles.end(); I != E; ++I) {
    lt_ptr ptr = lt_dlsym(*I, symbolName);
    if (ptr)
      return ptr;
  }

  // If this is darwin, it has some funky issues, try to solve them here.  Some
  // important symbols are marked 'private external' which doesn't allow
  // SearchForAddressOfSymbol to find them.  As such, we special case them here,
  // there is only a small handful of them.

#ifdef __APPLE__
#define EXPLICIT_SYMBOL(SYM) \
   extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM
  {
    EXPLICIT_SYMBOL(__ashldi3);
    EXPLICIT_SYMBOL(__ashrdi3);
    EXPLICIT_SYMBOL(__cmpdi2);
    EXPLICIT_SYMBOL(__divdi3);
    EXPLICIT_SYMBOL(__eprintf);
    EXPLICIT_SYMBOL(__fixdfdi);
    EXPLICIT_SYMBOL(__fixsfdi);
    EXPLICIT_SYMBOL(__fixunsdfdi);
    EXPLICIT_SYMBOL(__fixunssfdi);
    EXPLICIT_SYMBOL(__floatdidf);
    EXPLICIT_SYMBOL(__floatdisf);
    EXPLICIT_SYMBOL(__lshrdi3);
    EXPLICIT_SYMBOL(__moddi3);
    EXPLICIT_SYMBOL(__udivdi3);
    EXPLICIT_SYMBOL(__umoddi3);
  }
#undef EXPLICIT_SYMBOL
#endif

// This macro returns the address of a well-known, explicit symbol
#define EXPLICIT_SYMBOL(SYM) \
   if (!strcmp(symbolName, #SYM)) return &SYM

// On linux we have a weird situation. The stderr/out/in symbols are both
// macros and global variables because of standards requirements. So, we
// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
#if defined(__linux__)
  {
    EXPLICIT_SYMBOL(stderr);
    EXPLICIT_SYMBOL(stdout);
    EXPLICIT_SYMBOL(stdin);
  }
#else
  // For everything else, we want to check to make sure the symbol isn't defined
  // as a macro before using EXPLICIT_SYMBOL.
  {
#ifndef stdin
    EXPLICIT_SYMBOL(stdin);
#endif
#ifndef stdout
    EXPLICIT_SYMBOL(stdout);
#endif
#ifndef stderr
    EXPLICIT_SYMBOL(stderr);
#endif
  }
#endif
#undef EXPLICIT_SYMBOL

  return 0;
}

void *DynamicLibrary::GetAddressOfSymbol(const char *symbolName) {
  assert(handle != 0 && "Invalid DynamicLibrary handle");
  return lt_dlsym((lt_dlhandle) handle, symbolName);
}

#endif // LLVM_ON_WIN32

DEFINING_FILE_FOR(SystemDynamicLibrary)
<commit_msg>silence warning<commit_after>//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This header file implements the operating system DynamicLibrary concept.
//
//===----------------------------------------------------------------------===//

#include "llvm/System/DynamicLibrary.h"
#include "llvm/Config/config.h"
#include <map>

// Collection of symbol name/value pairs to be searched prior to any libraries.
static std::map<std::string, void *> g_symbols;

void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName,
                                          void *symbolValue) {
  g_symbols[symbolName] = symbolValue;
}

// It is not possible to use ltdl.c on VC++ builds as the terms of its LGPL
// license and special exception would cause all of LLVM to be placed under
// the LGPL.  This is because the exception applies only when libtool is
// used, and obviously libtool is not used with Visual Studio.  An entirely
// separate implementation is provided in win32/DynamicLibrary.cpp.

#ifdef LLVM_ON_WIN32

#include "Win32/DynamicLibrary.inc"

#else

#include "ltdl.h"
#include <cassert>
using namespace llvm;
using namespace llvm::sys;

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

static inline void check_ltdl_initialization() {
  static bool did_initialize_ltdl = false;
  if (!did_initialize_ltdl) {
    int Err = lt_dlinit();
    Err = Err; // Silence warning.
    assert(0 == Err && "Can't init the ltdl library");
    did_initialize_ltdl = true;
  }
}

static std::vector<lt_dlhandle> OpenedHandles;

DynamicLibrary::DynamicLibrary() : handle(0) {
  check_ltdl_initialization();

  lt_dlhandle a_handle = lt_dlopen(0);

  assert(a_handle == 0 || "Can't open program as dynamic library");

  handle = a_handle;
  OpenedHandles.push_back(a_handle);
}

/*
DynamicLibrary::DynamicLibrary(const char*filename) : handle(0) {
  check_ltdl_initialization();

  lt_dlhandle a_handle = lt_dlopen(filename);

  if (a_handle == 0)
    a_handle = lt_dlopenext(filename);

  if (a_handle == 0)
    throw std::string("Can't open :") + filename + ": " + lt_dlerror();

  handle = a_handle;
  OpenedHandles.push_back(a_handle);
}
*/

DynamicLibrary::~DynamicLibrary() {
  lt_dlhandle a_handle = (lt_dlhandle) handle;
  if (a_handle) {
    lt_dlclose(a_handle);

    for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(),
         E = OpenedHandles.end(); I != E; ++I) {
      if (*I == a_handle) {
        // Note: don't use the swap/pop_back trick here. Order is important.
        OpenedHandles.erase(I);
        return;
      }
    }
  }
}

bool DynamicLibrary::LoadLibraryPermanently(const char *Filename,
                                            std::string *ErrMsg) {
  check_ltdl_initialization();
  lt_dlhandle a_handle = lt_dlopen(Filename);

  if (a_handle == 0)
    a_handle = lt_dlopenext(Filename);

  if (a_handle == 0) {
    if (ErrMsg)
      *ErrMsg = std::string("Can't open :") +
          (Filename ? Filename : "<current process>") + ": " + lt_dlerror();
    return true;
  }

  lt_dlmakeresident(a_handle);

  OpenedHandles.push_back(a_handle);
  return false;
}

void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
  check_ltdl_initialization();

  // First check symbols added via AddSymbol().
  std::map<std::string, void *>::iterator I = g_symbols.find(symbolName);
  if (I != g_symbols.end())
    return I->second;

  // Now search the libraries.
  for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(),
       E = OpenedHandles.end(); I != E; ++I) {
    lt_ptr ptr = lt_dlsym(*I, symbolName);
    if (ptr)
      return ptr;
  }

  // If this is darwin, it has some funky issues, try to solve them here.  Some
  // important symbols are marked 'private external' which doesn't allow
  // SearchForAddressOfSymbol to find them.  As such, we special case them here,
  // there is only a small handful of them.

#ifdef __APPLE__
#define EXPLICIT_SYMBOL(SYM) \
   extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM
  {
    EXPLICIT_SYMBOL(__ashldi3);
    EXPLICIT_SYMBOL(__ashrdi3);
    EXPLICIT_SYMBOL(__cmpdi2);
    EXPLICIT_SYMBOL(__divdi3);
    EXPLICIT_SYMBOL(__eprintf);
    EXPLICIT_SYMBOL(__fixdfdi);
    EXPLICIT_SYMBOL(__fixsfdi);
    EXPLICIT_SYMBOL(__fixunsdfdi);
    EXPLICIT_SYMBOL(__fixunssfdi);
    EXPLICIT_SYMBOL(__floatdidf);
    EXPLICIT_SYMBOL(__floatdisf);
    EXPLICIT_SYMBOL(__lshrdi3);
    EXPLICIT_SYMBOL(__moddi3);
    EXPLICIT_SYMBOL(__udivdi3);
    EXPLICIT_SYMBOL(__umoddi3);
  }
#undef EXPLICIT_SYMBOL
#endif

// This macro returns the address of a well-known, explicit symbol
#define EXPLICIT_SYMBOL(SYM) \
   if (!strcmp(symbolName, #SYM)) return &SYM

// On linux we have a weird situation. The stderr/out/in symbols are both
// macros and global variables because of standards requirements. So, we
// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
#if defined(__linux__)
  {
    EXPLICIT_SYMBOL(stderr);
    EXPLICIT_SYMBOL(stdout);
    EXPLICIT_SYMBOL(stdin);
  }
#else
  // For everything else, we want to check to make sure the symbol isn't defined
  // as a macro before using EXPLICIT_SYMBOL.
  {
#ifndef stdin
    EXPLICIT_SYMBOL(stdin);
#endif
#ifndef stdout
    EXPLICIT_SYMBOL(stdout);
#endif
#ifndef stderr
    EXPLICIT_SYMBOL(stderr);
#endif
  }
#endif
#undef EXPLICIT_SYMBOL

  return 0;
}

void *DynamicLibrary::GetAddressOfSymbol(const char *symbolName) {
  assert(handle != 0 && "Invalid DynamicLibrary handle");
  return lt_dlsym((lt_dlhandle) handle, symbolName);
}

#endif // LLVM_ON_WIN32

DEFINING_FILE_FOR(SystemDynamicLibrary)
<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_privsep_helper.h"
#include "condor_debug.h"

// the methods in this file are all stubbed out for now, until we
// have support for privilege separation on Windows

bool CondorPrivSepHelper::s_instantiated = false;

CondorPrivSepHelper::CondorPrivSepHelper() :
	m_user_initialized(false),
	m_user_name(NULL),
	m_sandbox_initialized(false),
	m_sandbox_path(NULL)
{
	ASSERT(!s_instantiated);
	s_instantiated = true;
}

CondorPrivSepHelper::~CondorPrivSepHelper()
{
	if (m_sandbox_path != NULL) {
		free(m_sandbox_path);
	}
	if( m_user_name ) {
		free(m_user_name);
	}
}

void
CondorPrivSepHelper::initialize_user(const char* name)
{
	m_user_name = strdup(name);

	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
}

char const *
CondorPrivSepHelper::get_user_name()
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
	return m_user_name;
}

void
CondorPrivSepHelper::initialize_sandbox(const char* path)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
}

bool
CondorPrivSepHelper::chown_sandbox_to_user(PrivSepError &)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
	return false;
}

bool
CondorPrivSepHelper::chown_sandbox_to_condor(PrivSepError &)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
	return false;
}

int
CondorPrivSepHelper::create_process(const char*,
                                     ArgList&,
                                     Env&,
                                     const char*,
                                     int[3],
                                     const char*[3],
                                     int,
                                     size_t*,
                                     int,
                                     int,
                                     FamilyInfo*,
                                     int *affinity_mask,
                                     MyString *  error_msg /*= NULL*/)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
	return 0;
}
<commit_msg>stub the CondorPrivSepHelper::get_exec_dir_usage method on Windows #3326<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_privsep_helper.h"
#include "condor_debug.h"

// the methods in this file are all stubbed out for now, until we
// have support for privilege separation on Windows

bool CondorPrivSepHelper::s_instantiated = false;

CondorPrivSepHelper::CondorPrivSepHelper() :
	m_user_initialized(false),
	m_user_name(NULL),
	m_sandbox_initialized(false),
	m_sandbox_path(NULL)
{
	ASSERT(!s_instantiated);
	s_instantiated = true;
}

CondorPrivSepHelper::~CondorPrivSepHelper()
{
	if (m_sandbox_path != NULL) {
		free(m_sandbox_path);
	}
	if( m_user_name ) {
		free(m_user_name);
	}
}

void
CondorPrivSepHelper::initialize_user(const char* name)
{
	m_user_name = strdup(name);

	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
}

char const *
CondorPrivSepHelper::get_user_name()
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
	return m_user_name;
}

void
CondorPrivSepHelper::initialize_sandbox(const char* path)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
}

bool
CondorPrivSepHelper::get_exec_dir_usage(off_t *usage)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
}

bool
CondorPrivSepHelper::chown_sandbox_to_user(PrivSepError &)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
	return false;
}

bool
CondorPrivSepHelper::chown_sandbox_to_condor(PrivSepError &)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
	return false;
}

int
CondorPrivSepHelper::create_process(const char*,
                                     ArgList&,
                                     Env&,
                                     const char*,
                                     int[3],
                                     const char*[3],
                                     int,
                                     size_t*,
                                     int,
                                     int,
                                     FamilyInfo*,
                                     int *affinity_mask,
                                     MyString *  error_msg /*= NULL*/)
{
	EXCEPT("CondorPrivSepHelper: Windows support not implemented");
	return 0;
}
<|endoftext|>


<commit_before>//===-- LanaiMemAluCombiner.cpp - Pass to combine memory & ALU operations -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Simple pass to combine memory and ALU operations
//
// The Lanai ISA supports instructions where a load/store modifies the base
// register used in the load/store operation. This pass finds suitable
// load/store and ALU instructions and combines them into one instruction.
//
// For example,
//   ld [ %r6 -- ], %r12
// is a supported instruction that is not currently generated by the instruction
// selection pass of this backend. This pass generates these instructions by
// merging
//   add %r6, -4, %r6
// followed by
//   ld [ %r6 ], %r12
// in the same machine basic block into one machine instruction.
//===----------------------------------------------------------------------===//

#include "Lanai.h"
#include "LanaiTargetMachine.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

#define GET_INSTRMAP_INFO
#include "LanaiGenInstrInfo.inc"

#define DEBUG_TYPE "lanai-mem-alu-combiner"

STATISTIC(NumLdStAluCombined, "Number of memory and ALU instructions combined");

static llvm::cl::opt<bool> DisableMemAluCombiner(
    "disable-lanai-mem-alu-combiner", llvm::cl::init(false),
    llvm::cl::desc("Do not combine ALU and memory operators"),
    llvm::cl::Hidden);

namespace llvm {
void initializeLanaiMemAluCombinerPass(PassRegistry &);
} // namespace llvm

namespace {
typedef MachineBasicBlock::iterator MbbIterator;
typedef MachineFunction::iterator MfIterator;

class LanaiMemAluCombiner : public MachineFunctionPass {
public:
  static char ID;
  explicit LanaiMemAluCombiner() : MachineFunctionPass(ID) {
    initializeLanaiMemAluCombinerPass(*PassRegistry::getPassRegistry());
  }

  StringRef getPassName() const override {
    return "Lanai load / store optimization pass";
  }

  bool runOnMachineFunction(MachineFunction &F) override;

  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().set(
        MachineFunctionProperties::Property::NoVRegs);
  }

private:
  MbbIterator findClosestSuitableAluInstr(MachineBasicBlock *BB,
                                          const MbbIterator &MemInstr,
                                          bool Decrement);
  void insertMergedInstruction(MachineBasicBlock *BB,
                               const MbbIterator &MemInstr,
                               const MbbIterator &AluInstr, bool Before);
  bool combineMemAluInBasicBlock(MachineBasicBlock *BB);

  // Target machine description which we query for register names, data
  // layout, etc.
  const TargetInstrInfo *TII;
};
} // namespace

char LanaiMemAluCombiner::ID = 0;

INITIALIZE_PASS(LanaiMemAluCombiner, DEBUG_TYPE,
                "Lanai memory ALU combiner pass", false, false)

namespace {
bool isSpls(uint16_t Opcode) { return Lanai::splsIdempotent(Opcode) == Opcode; }

// Determine the opcode for the merged instruction created by considering the
// old memory operation's opcode and whether the merged opcode will have an
// immediate offset.
unsigned mergedOpcode(unsigned OldOpcode, bool ImmediateOffset) {
  switch (OldOpcode) {
  case Lanai::LDW_RI:
  case Lanai::LDW_RR:
    if (ImmediateOffset)
      return Lanai::LDW_RI;
    return Lanai::LDW_RR;
  case Lanai::LDHs_RI:
  case Lanai::LDHs_RR:
    if (ImmediateOffset)
      return Lanai::LDHs_RI;
    return Lanai::LDHs_RR;
  case Lanai::LDHz_RI:
  case Lanai::LDHz_RR:
    if (ImmediateOffset)
      return Lanai::LDHz_RI;
    return Lanai::LDHz_RR;
  case Lanai::LDBs_RI:
  case Lanai::LDBs_RR:
    if (ImmediateOffset)
      return Lanai::LDBs_RI;
    return Lanai::LDBs_RR;
  case Lanai::LDBz_RI:
  case Lanai::LDBz_RR:
    if (ImmediateOffset)
      return Lanai::LDBz_RI;
    return Lanai::LDBz_RR;
  case Lanai::SW_RI:
  case Lanai::SW_RR:
    if (ImmediateOffset)
      return Lanai::SW_RI;
    return Lanai::SW_RR;
  case Lanai::STB_RI:
  case Lanai::STB_RR:
    if (ImmediateOffset)
      return Lanai::STB_RI;
    return Lanai::STB_RR;
  case Lanai::STH_RI:
  case Lanai::STH_RR:
    if (ImmediateOffset)
      return Lanai::STH_RI;
    return Lanai::STH_RR;
  default:
    return 0;
  }
}

// Check if the machine instruction has non-volatile memory operands of the type
// supported for combining with ALU instructions.
bool isNonVolatileMemoryOp(const MachineInstr &MI) {
  if (!MI.hasOneMemOperand())
    return false;

  // Determine if the machine instruction is a supported memory operation by
  // testing if the computed merge opcode is a valid memory operation opcode.
  if (mergedOpcode(MI.getOpcode(), false) == 0)
    return false;

  const MachineMemOperand *MemOperand = *MI.memoperands_begin();

  // Don't move volatile memory accesses
  // TODO: unclear if we need to be as conservative about atomics
  if (MemOperand->isVolatile() || MemOperand->isAtomic())
    return false;

  return true;
}

// Test to see if two machine operands are of the same type. This test is less
// strict than the MachineOperand::isIdenticalTo function.
bool isSameOperand(const MachineOperand &Op1, const MachineOperand &Op2) {
  if (Op1.getType() != Op2.getType())
    return false;

  switch (Op1.getType()) {
  case MachineOperand::MO_Register:
    return Op1.getReg() == Op2.getReg();
  case MachineOperand::MO_Immediate:
    return Op1.getImm() == Op2.getImm();
  default:
    return false;
  }
}

bool isZeroOperand(const MachineOperand &Op) {
  return ((Op.isReg() && Op.getReg() == Lanai::R0) ||
          (Op.isImm() && Op.getImm() == 0));
}

// Determines whether a register is used by an instruction.
bool InstrUsesReg(const MbbIterator &Instr, const MachineOperand *Reg) {
  for (MachineInstr::const_mop_iterator Mop = Instr->operands_begin();
       Mop != Instr->operands_end(); ++Mop) {
    if (isSameOperand(*Mop, *Reg))
      return true;
  }
  return false;
}

// Converts between machine opcode and AluCode.
// Flag using/modifying ALU operations should not be considered for merging and
// are omitted from this list.
LPAC::AluCode mergedAluCode(unsigned AluOpcode) {
  switch (AluOpcode) {
  case Lanai::ADD_I_LO:
  case Lanai::ADD_R:
    return LPAC::ADD;
  case Lanai::SUB_I_LO:
  case Lanai::SUB_R:
    return LPAC::SUB;
  case Lanai::AND_I_LO:
  case Lanai::AND_R:
    return LPAC::AND;
  case Lanai::OR_I_LO:
  case Lanai::OR_R:
    return LPAC::OR;
  case Lanai::XOR_I_LO:
  case Lanai::XOR_R:
    return LPAC::XOR;
  case Lanai::SHL_R:
    return LPAC::SHL;
  case Lanai::SRL_R:
    return LPAC::SRL;
  case Lanai::SRA_R:
    return LPAC::SRA;
  case Lanai::SA_I:
  case Lanai::SL_I:
  default:
    return LPAC::UNKNOWN;
  }
}

// Insert a new combined memory and ALU operation instruction.
//
// This function builds a new machine instruction using the MachineInstrBuilder
// class and inserts it before the memory instruction.
void LanaiMemAluCombiner::insertMergedInstruction(MachineBasicBlock *BB,
                                                  const MbbIterator &MemInstr,
                                                  const MbbIterator &AluInstr,
                                                  bool Before) {
  // Insert new combined load/store + alu operation
  MachineOperand Dest = MemInstr->getOperand(0);
  MachineOperand Base = MemInstr->getOperand(1);
  MachineOperand MemOffset = MemInstr->getOperand(2);
  MachineOperand AluOffset = AluInstr->getOperand(2);

  // Abort if ALU offset is not a register or immediate
  assert((AluOffset.isReg() || AluOffset.isImm()) &&
         "Unsupported operand type in merge");

  // Determined merged instructions opcode and ALU code
  LPAC::AluCode AluOpcode = mergedAluCode(AluInstr->getOpcode());
  unsigned NewOpc = mergedOpcode(MemInstr->getOpcode(), AluOffset.isImm());

  assert(AluOpcode != LPAC::UNKNOWN && "Unknown ALU code in merging");
  assert(NewOpc != 0 && "Unknown merged node opcode");

  // Build and insert new machine instruction
  MachineInstrBuilder InstrBuilder =
      BuildMI(*BB, MemInstr, MemInstr->getDebugLoc(), TII->get(NewOpc));
  InstrBuilder.addReg(Dest.getReg(), getDefRegState(true));
  InstrBuilder.addReg(Base.getReg(), getKillRegState(true));

  // Add offset to machine instruction
  if (AluOffset.isReg())
    InstrBuilder.addReg(AluOffset.getReg());
  else if (AluOffset.isImm())
    InstrBuilder.addImm(AluOffset.getImm());
  else
    llvm_unreachable("Unsupported ld/st ALU merge.");

  // Create a pre-op if the ALU operation preceded the memory operation or the
  // MemOffset is non-zero (i.e. the memory value should be adjusted before
  // accessing it), else create a post-op.
  if (Before || !isZeroOperand(MemOffset))
    InstrBuilder.addImm(LPAC::makePreOp(AluOpcode));
  else
    InstrBuilder.addImm(LPAC::makePostOp(AluOpcode));

  // Transfer memory operands.
  InstrBuilder.setMemRefs(MemInstr->memoperands());
}

// Function determines if ALU operation (in alu_iter) can be combined with
// a load/store with base and offset.
bool isSuitableAluInstr(bool IsSpls, const MbbIterator &AluIter,
                        const MachineOperand &Base,
                        const MachineOperand &Offset) {
  // ALU operations have 3 operands
  if (AluIter->getNumOperands() != 3)
    return false;

  MachineOperand &Dest = AluIter->getOperand(0);
  MachineOperand &Op1 = AluIter->getOperand(1);
  MachineOperand &Op2 = AluIter->getOperand(2);

  // Only match instructions using the base register as destination and with the
  // base and first operand equal
  if (!isSameOperand(Dest, Base) || !isSameOperand(Dest, Op1))
    return false;

  if (Op2.isImm()) {
    // It is not a match if the 2nd operand in the ALU operation is an
    // immediate but the ALU operation is not an addition.
    if (AluIter->getOpcode() != Lanai::ADD_I_LO)
      return false;

    if (Offset.isReg() && Offset.getReg() == Lanai::R0)
      return true;

    if (Offset.isImm() &&
        ((Offset.getImm() == 0 &&
          // Check that the Op2 would fit in the immediate field of the
          // memory operation.
          ((IsSpls && isInt<10>(Op2.getImm())) ||
           (!IsSpls && isInt<16>(Op2.getImm())))) ||
         Offset.getImm() == Op2.getImm()))
      return true;
  } else if (Op2.isReg()) {
    // The Offset and 2nd operand are both registers and equal
    if (Offset.isReg() && Op2.getReg() == Offset.getReg())
      return true;
  } else
    // Only consider operations with register or immediate values
    return false;

  return false;
}

MbbIterator LanaiMemAluCombiner::findClosestSuitableAluInstr(
    MachineBasicBlock *BB, const MbbIterator &MemInstr, const bool Decrement) {
  MachineOperand *Base = &MemInstr->getOperand(1);
  MachineOperand *Offset = &MemInstr->getOperand(2);
  bool IsSpls = isSpls(MemInstr->getOpcode());

  MbbIterator First = MemInstr;
  MbbIterator Last = Decrement ? BB->begin() : BB->end();

  while (First != Last) {
    Decrement ? --First : ++First;

    if (First == Last)
      break;

    // Skip over debug instructions
    if (First->isDebugInstr())
      continue;

    if (isSuitableAluInstr(IsSpls, First, *Base, *Offset)) {
      return First;
    }

    // Usage of the base or offset register is not a form suitable for merging.
    if (First != Last) {
      if (InstrUsesReg(First, Base))
        break;
      if (Offset->isReg() && InstrUsesReg(First, Offset))
        break;
    }
  }

  return MemInstr;
}

bool LanaiMemAluCombiner::combineMemAluInBasicBlock(MachineBasicBlock *BB) {
  bool Modified = false;

  MbbIterator MBBIter = BB->begin(), End = BB->end();
  while (MBBIter != End) {
    bool IsMemOp = isNonVolatileMemoryOp(*MBBIter);

    if (IsMemOp) {
      MachineOperand AluOperand = MBBIter->getOperand(3);
      unsigned int DestReg = MBBIter->getOperand(0).getReg(),
                   BaseReg = MBBIter->getOperand(1).getReg();
      assert(AluOperand.isImm() && "Unexpected memory operator type");
      LPAC::AluCode AluOpcode = static_cast<LPAC::AluCode>(AluOperand.getImm());

      // Skip memory operations that already modify the base register or if
      // the destination and base register are the same
      if (!LPAC::modifiesOp(AluOpcode) && DestReg != BaseReg) {
        for (int Inc = 0; Inc <= 1; ++Inc) {
          MbbIterator AluIter =
              findClosestSuitableAluInstr(BB, MBBIter, Inc == 0);
          if (AluIter != MBBIter) {
            insertMergedInstruction(BB, MBBIter, AluIter, Inc == 0);

            ++NumLdStAluCombined;
            Modified = true;

            // Erase the matching ALU instruction
            BB->erase(AluIter);
            // Erase old load/store instruction
            BB->erase(MBBIter++);
            break;
          }
        }
      }
    }
    if (MBBIter == End)
      break;
    ++MBBIter;
  }

  return Modified;
}

// Driver function that iterates over the machine basic building blocks of a
// machine function
bool LanaiMemAluCombiner::runOnMachineFunction(MachineFunction &MF) {
  if (DisableMemAluCombiner)
    return false;

  TII = MF.getSubtarget<LanaiSubtarget>().getInstrInfo();
  bool Modified = false;
  for (MfIterator MFI = MF.begin(); MFI != MF.end(); ++MFI) {
    Modified |= combineMemAluInBasicBlock(&*MFI);
  }
  return Modified;
}
} // namespace

FunctionPass *llvm::createLanaiMemAluCombinerPass() {
  return new LanaiMemAluCombiner();
}
<commit_msg>Include what you use in LanaiMemAluCombiner.cpp<commit_after>//===-- LanaiMemAluCombiner.cpp - Pass to combine memory & ALU operations -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Simple pass to combine memory and ALU operations
//
// The Lanai ISA supports instructions where a load/store modifies the base
// register used in the load/store operation. This pass finds suitable
// load/store and ALU instructions and combines them into one instruction.
//
// For example,
//   ld [ %r6 -- ], %r12
// is a supported instruction that is not currently generated by the instruction
// selection pass of this backend. This pass generates these instructions by
// merging
//   add %r6, -4, %r6
// followed by
//   ld [ %r6 ], %r12
// in the same machine basic block into one machine instruction.
//===----------------------------------------------------------------------===//

#include "LanaiAluCode.h"
#include "LanaiTargetMachine.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

#define GET_INSTRMAP_INFO
#include "LanaiGenInstrInfo.inc"

#define DEBUG_TYPE "lanai-mem-alu-combiner"

STATISTIC(NumLdStAluCombined, "Number of memory and ALU instructions combined");

static llvm::cl::opt<bool> DisableMemAluCombiner(
    "disable-lanai-mem-alu-combiner", llvm::cl::init(false),
    llvm::cl::desc("Do not combine ALU and memory operators"),
    llvm::cl::Hidden);

namespace llvm {
void initializeLanaiMemAluCombinerPass(PassRegistry &);
} // namespace llvm

namespace {
typedef MachineBasicBlock::iterator MbbIterator;
typedef MachineFunction::iterator MfIterator;

class LanaiMemAluCombiner : public MachineFunctionPass {
public:
  static char ID;
  explicit LanaiMemAluCombiner() : MachineFunctionPass(ID) {
    initializeLanaiMemAluCombinerPass(*PassRegistry::getPassRegistry());
  }

  StringRef getPassName() const override {
    return "Lanai load / store optimization pass";
  }

  bool runOnMachineFunction(MachineFunction &F) override;

  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().set(
        MachineFunctionProperties::Property::NoVRegs);
  }

private:
  MbbIterator findClosestSuitableAluInstr(MachineBasicBlock *BB,
                                          const MbbIterator &MemInstr,
                                          bool Decrement);
  void insertMergedInstruction(MachineBasicBlock *BB,
                               const MbbIterator &MemInstr,
                               const MbbIterator &AluInstr, bool Before);
  bool combineMemAluInBasicBlock(MachineBasicBlock *BB);

  // Target machine description which we query for register names, data
  // layout, etc.
  const TargetInstrInfo *TII;
};
} // namespace

char LanaiMemAluCombiner::ID = 0;

INITIALIZE_PASS(LanaiMemAluCombiner, DEBUG_TYPE,
                "Lanai memory ALU combiner pass", false, false)

namespace {
bool isSpls(uint16_t Opcode) { return Lanai::splsIdempotent(Opcode) == Opcode; }

// Determine the opcode for the merged instruction created by considering the
// old memory operation's opcode and whether the merged opcode will have an
// immediate offset.
unsigned mergedOpcode(unsigned OldOpcode, bool ImmediateOffset) {
  switch (OldOpcode) {
  case Lanai::LDW_RI:
  case Lanai::LDW_RR:
    if (ImmediateOffset)
      return Lanai::LDW_RI;
    return Lanai::LDW_RR;
  case Lanai::LDHs_RI:
  case Lanai::LDHs_RR:
    if (ImmediateOffset)
      return Lanai::LDHs_RI;
    return Lanai::LDHs_RR;
  case Lanai::LDHz_RI:
  case Lanai::LDHz_RR:
    if (ImmediateOffset)
      return Lanai::LDHz_RI;
    return Lanai::LDHz_RR;
  case Lanai::LDBs_RI:
  case Lanai::LDBs_RR:
    if (ImmediateOffset)
      return Lanai::LDBs_RI;
    return Lanai::LDBs_RR;
  case Lanai::LDBz_RI:
  case Lanai::LDBz_RR:
    if (ImmediateOffset)
      return Lanai::LDBz_RI;
    return Lanai::LDBz_RR;
  case Lanai::SW_RI:
  case Lanai::SW_RR:
    if (ImmediateOffset)
      return Lanai::SW_RI;
    return Lanai::SW_RR;
  case Lanai::STB_RI:
  case Lanai::STB_RR:
    if (ImmediateOffset)
      return Lanai::STB_RI;
    return Lanai::STB_RR;
  case Lanai::STH_RI:
  case Lanai::STH_RR:
    if (ImmediateOffset)
      return Lanai::STH_RI;
    return Lanai::STH_RR;
  default:
    return 0;
  }
}

// Check if the machine instruction has non-volatile memory operands of the type
// supported for combining with ALU instructions.
bool isNonVolatileMemoryOp(const MachineInstr &MI) {
  if (!MI.hasOneMemOperand())
    return false;

  // Determine if the machine instruction is a supported memory operation by
  // testing if the computed merge opcode is a valid memory operation opcode.
  if (mergedOpcode(MI.getOpcode(), false) == 0)
    return false;

  const MachineMemOperand *MemOperand = *MI.memoperands_begin();

  // Don't move volatile memory accesses
  // TODO: unclear if we need to be as conservative about atomics
  if (MemOperand->isVolatile() || MemOperand->isAtomic())
    return false;

  return true;
}

// Test to see if two machine operands are of the same type. This test is less
// strict than the MachineOperand::isIdenticalTo function.
bool isSameOperand(const MachineOperand &Op1, const MachineOperand &Op2) {
  if (Op1.getType() != Op2.getType())
    return false;

  switch (Op1.getType()) {
  case MachineOperand::MO_Register:
    return Op1.getReg() == Op2.getReg();
  case MachineOperand::MO_Immediate:
    return Op1.getImm() == Op2.getImm();
  default:
    return false;
  }
}

bool isZeroOperand(const MachineOperand &Op) {
  return ((Op.isReg() && Op.getReg() == Lanai::R0) ||
          (Op.isImm() && Op.getImm() == 0));
}

// Determines whether a register is used by an instruction.
bool InstrUsesReg(const MbbIterator &Instr, const MachineOperand *Reg) {
  for (MachineInstr::const_mop_iterator Mop = Instr->operands_begin();
       Mop != Instr->operands_end(); ++Mop) {
    if (isSameOperand(*Mop, *Reg))
      return true;
  }
  return false;
}

// Converts between machine opcode and AluCode.
// Flag using/modifying ALU operations should not be considered for merging and
// are omitted from this list.
LPAC::AluCode mergedAluCode(unsigned AluOpcode) {
  switch (AluOpcode) {
  case Lanai::ADD_I_LO:
  case Lanai::ADD_R:
    return LPAC::ADD;
  case Lanai::SUB_I_LO:
  case Lanai::SUB_R:
    return LPAC::SUB;
  case Lanai::AND_I_LO:
  case Lanai::AND_R:
    return LPAC::AND;
  case Lanai::OR_I_LO:
  case Lanai::OR_R:
    return LPAC::OR;
  case Lanai::XOR_I_LO:
  case Lanai::XOR_R:
    return LPAC::XOR;
  case Lanai::SHL_R:
    return LPAC::SHL;
  case Lanai::SRL_R:
    return LPAC::SRL;
  case Lanai::SRA_R:
    return LPAC::SRA;
  case Lanai::SA_I:
  case Lanai::SL_I:
  default:
    return LPAC::UNKNOWN;
  }
}

// Insert a new combined memory and ALU operation instruction.
//
// This function builds a new machine instruction using the MachineInstrBuilder
// class and inserts it before the memory instruction.
void LanaiMemAluCombiner::insertMergedInstruction(MachineBasicBlock *BB,
                                                  const MbbIterator &MemInstr,
                                                  const MbbIterator &AluInstr,
                                                  bool Before) {
  // Insert new combined load/store + alu operation
  MachineOperand Dest = MemInstr->getOperand(0);
  MachineOperand Base = MemInstr->getOperand(1);
  MachineOperand MemOffset = MemInstr->getOperand(2);
  MachineOperand AluOffset = AluInstr->getOperand(2);

  // Abort if ALU offset is not a register or immediate
  assert((AluOffset.isReg() || AluOffset.isImm()) &&
         "Unsupported operand type in merge");

  // Determined merged instructions opcode and ALU code
  LPAC::AluCode AluOpcode = mergedAluCode(AluInstr->getOpcode());
  unsigned NewOpc = mergedOpcode(MemInstr->getOpcode(), AluOffset.isImm());

  assert(AluOpcode != LPAC::UNKNOWN && "Unknown ALU code in merging");
  assert(NewOpc != 0 && "Unknown merged node opcode");

  // Build and insert new machine instruction
  MachineInstrBuilder InstrBuilder =
      BuildMI(*BB, MemInstr, MemInstr->getDebugLoc(), TII->get(NewOpc));
  InstrBuilder.addReg(Dest.getReg(), getDefRegState(true));
  InstrBuilder.addReg(Base.getReg(), getKillRegState(true));

  // Add offset to machine instruction
  if (AluOffset.isReg())
    InstrBuilder.addReg(AluOffset.getReg());
  else if (AluOffset.isImm())
    InstrBuilder.addImm(AluOffset.getImm());
  else
    llvm_unreachable("Unsupported ld/st ALU merge.");

  // Create a pre-op if the ALU operation preceded the memory operation or the
  // MemOffset is non-zero (i.e. the memory value should be adjusted before
  // accessing it), else create a post-op.
  if (Before || !isZeroOperand(MemOffset))
    InstrBuilder.addImm(LPAC::makePreOp(AluOpcode));
  else
    InstrBuilder.addImm(LPAC::makePostOp(AluOpcode));

  // Transfer memory operands.
  InstrBuilder.setMemRefs(MemInstr->memoperands());
}

// Function determines if ALU operation (in alu_iter) can be combined with
// a load/store with base and offset.
bool isSuitableAluInstr(bool IsSpls, const MbbIterator &AluIter,
                        const MachineOperand &Base,
                        const MachineOperand &Offset) {
  // ALU operations have 3 operands
  if (AluIter->getNumOperands() != 3)
    return false;

  MachineOperand &Dest = AluIter->getOperand(0);
  MachineOperand &Op1 = AluIter->getOperand(1);
  MachineOperand &Op2 = AluIter->getOperand(2);

  // Only match instructions using the base register as destination and with the
  // base and first operand equal
  if (!isSameOperand(Dest, Base) || !isSameOperand(Dest, Op1))
    return false;

  if (Op2.isImm()) {
    // It is not a match if the 2nd operand in the ALU operation is an
    // immediate but the ALU operation is not an addition.
    if (AluIter->getOpcode() != Lanai::ADD_I_LO)
      return false;

    if (Offset.isReg() && Offset.getReg() == Lanai::R0)
      return true;

    if (Offset.isImm() &&
        ((Offset.getImm() == 0 &&
          // Check that the Op2 would fit in the immediate field of the
          // memory operation.
          ((IsSpls && isInt<10>(Op2.getImm())) ||
           (!IsSpls && isInt<16>(Op2.getImm())))) ||
         Offset.getImm() == Op2.getImm()))
      return true;
  } else if (Op2.isReg()) {
    // The Offset and 2nd operand are both registers and equal
    if (Offset.isReg() && Op2.getReg() == Offset.getReg())
      return true;
  } else
    // Only consider operations with register or immediate values
    return false;

  return false;
}

MbbIterator LanaiMemAluCombiner::findClosestSuitableAluInstr(
    MachineBasicBlock *BB, const MbbIterator &MemInstr, const bool Decrement) {
  MachineOperand *Base = &MemInstr->getOperand(1);
  MachineOperand *Offset = &MemInstr->getOperand(2);
  bool IsSpls = isSpls(MemInstr->getOpcode());

  MbbIterator First = MemInstr;
  MbbIterator Last = Decrement ? BB->begin() : BB->end();

  while (First != Last) {
    Decrement ? --First : ++First;

    if (First == Last)
      break;

    // Skip over debug instructions
    if (First->isDebugInstr())
      continue;

    if (isSuitableAluInstr(IsSpls, First, *Base, *Offset)) {
      return First;
    }

    // Usage of the base or offset register is not a form suitable for merging.
    if (First != Last) {
      if (InstrUsesReg(First, Base))
        break;
      if (Offset->isReg() && InstrUsesReg(First, Offset))
        break;
    }
  }

  return MemInstr;
}

bool LanaiMemAluCombiner::combineMemAluInBasicBlock(MachineBasicBlock *BB) {
  bool Modified = false;

  MbbIterator MBBIter = BB->begin(), End = BB->end();
  while (MBBIter != End) {
    bool IsMemOp = isNonVolatileMemoryOp(*MBBIter);

    if (IsMemOp) {
      MachineOperand AluOperand = MBBIter->getOperand(3);
      unsigned int DestReg = MBBIter->getOperand(0).getReg(),
                   BaseReg = MBBIter->getOperand(1).getReg();
      assert(AluOperand.isImm() && "Unexpected memory operator type");
      LPAC::AluCode AluOpcode = static_cast<LPAC::AluCode>(AluOperand.getImm());

      // Skip memory operations that already modify the base register or if
      // the destination and base register are the same
      if (!LPAC::modifiesOp(AluOpcode) && DestReg != BaseReg) {
        for (int Inc = 0; Inc <= 1; ++Inc) {
          MbbIterator AluIter =
              findClosestSuitableAluInstr(BB, MBBIter, Inc == 0);
          if (AluIter != MBBIter) {
            insertMergedInstruction(BB, MBBIter, AluIter, Inc == 0);

            ++NumLdStAluCombined;
            Modified = true;

            // Erase the matching ALU instruction
            BB->erase(AluIter);
            // Erase old load/store instruction
            BB->erase(MBBIter++);
            break;
          }
        }
      }
    }
    if (MBBIter == End)
      break;
    ++MBBIter;
  }

  return Modified;
}

// Driver function that iterates over the machine basic building blocks of a
// machine function
bool LanaiMemAluCombiner::runOnMachineFunction(MachineFunction &MF) {
  if (DisableMemAluCombiner)
    return false;

  TII = MF.getSubtarget<LanaiSubtarget>().getInstrInfo();
  bool Modified = false;
  for (MfIterator MFI = MF.begin(); MFI != MF.end(); ++MFI) {
    Modified |= combineMemAluInBasicBlock(&*MFI);
  }
  return Modified;
}
} // namespace

FunctionPass *llvm::createLanaiMemAluCombinerPass() {
  return new LanaiMemAluCombiner();
}
<|endoftext|>


<commit_before>//===-- PPCBranchSelector.cpp - Emit long conditional branches-----*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Baegeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that scans a machine function to determine which
// conditional branches need more than 16 bits of displacement to reach their
// target basic block.  It does this in two passes; a calculation of basic block
// positions pass, and a branch psuedo op to machine branch opcode pass.  This
// pass should be run last, just before the assembly printer.
//
//===----------------------------------------------------------------------===//

#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCInstrInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include <map>
using namespace llvm;

static Statistic<> NumExpanded("ppc-branch-select",
                               "Num branches expanded to long format");

namespace {
  struct VISIBILITY_HIDDEN PPCBSel : public MachineFunctionPass {
    /// OffsetMap - Mapping between BB and byte offset from start of function.
    /// TODO: replace this with a vector, using the MBB idx as the key.
    std::map<MachineBasicBlock*, unsigned> OffsetMap;

    virtual bool runOnMachineFunction(MachineFunction &Fn);

    virtual const char *getPassName() const {
      return "PowerPC Branch Selection";
    }
  };
}

/// createPPCBranchSelectionPass - returns an instance of the Branch Selection
/// Pass
///
FunctionPass *llvm::createPPCBranchSelectionPass() {
  return new PPCBSel();
}

/// getNumBytesForInstruction - Return the number of bytes of code the specified
/// instruction may be.  This returns the maximum number of bytes.
///
static unsigned getNumBytesForInstruction(MachineInstr *MI) {
  switch (MI->getOpcode()) {
  case PPC::COND_BRANCH:
    // while this will be 4 most of the time, if we emit 8 it is just a
    // minor pessimization that saves us from having to worry about
    // keeping the offsets up to date later when we emit long branch glue.
    return 8;
  case PPC::IMPLICIT_DEF_GPRC: // no asm emitted
  case PPC::IMPLICIT_DEF_G8RC: // no asm emitted
  case PPC::IMPLICIT_DEF_F4:   // no asm emitted
  case PPC::IMPLICIT_DEF_F8:   // no asm emitted
    return 0;
  case PPC::INLINEASM: {       // Inline Asm: Variable size.
    MachineFunction *MF = MI->getParent()->getParent();
    const char *AsmStr = MI->getOperand(0).getSymbolName();
    return MF->getTarget().getTargetAsmInfo()->getInlineAsmLength(AsmStr);
  }
  default:
    return 4; // PowerPC instructions are all 4 bytes
  }
}

bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
  // Running total of instructions encountered since beginning of function
  unsigned ByteCount = 0;

  // For each MBB, add its offset to the offset map, and count up its
  // instructions
  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {
    MachineBasicBlock *MBB = MFI;
    OffsetMap[MBB] = ByteCount;

    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
         MBBI != EE; ++MBBI)
      ByteCount += getNumBytesForInstruction(MBBI);
  }

  // We're about to run over the MBB's again, so reset the ByteCount
  ByteCount = 0;

  // For each MBB, find the conditional branch pseudo instructions, and
  // calculate the difference between the target MBB and the current ICount
  // to decide whether or not to emit a short or long branch.
  //
  // short branch:
  // bCC .L_TARGET_MBB
  //
  // long branch:
  // bInverseCC $PC+8
  // b .L_TARGET_MBB
  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {
    MachineBasicBlock *MBB = MFI;

    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
         MBBI != EE; ++MBBI) {
      // We may end up deleting the MachineInstr that MBBI points to, so
      // remember its opcode now so we can refer to it after calling erase()
      unsigned ByteSize = getNumBytesForInstruction(MBBI);
      if (MBBI->getOpcode() == PPC::COND_BRANCH) {
        MachineBasicBlock::iterator MBBJ = MBBI;
        ++MBBJ;

        // condbranch operands:
        // 0. CR0 register
        // 1. bc opcode
        // 2. target MBB
        // 3. fallthrough MBB
        MachineBasicBlock *trueMBB =
          MBBI->getOperand(2).getMachineBasicBlock();

        int Displacement = OffsetMap[trueMBB] - ByteCount;
        unsigned Opcode = MBBI->getOperand(1).getImmedValue();
        unsigned CRReg = MBBI->getOperand(0).getReg();
        unsigned Inverted = PPCInstrInfo::invertPPCBranchOpcode(Opcode);

        if (Displacement >= -32768 && Displacement <= 32767) {
          BuildMI(*MBB, MBBJ, Opcode, 2).addReg(CRReg).addMBB(trueMBB);
        } else {
          // Long branch, skip next branch instruction (i.e. $PC+8).
          ++NumExpanded;
          BuildMI(*MBB, MBBJ, Inverted, 2).addReg(CRReg).addImm(2);
          BuildMI(*MBB, MBBJ, PPC::B, 1).addMBB(trueMBB);
        }

        // Erase the psuedo COND_BRANCH instruction, and then back up the
        // iterator so that when the for loop increments it, we end up in
        // the correct place rather than iterating off the end.
        MBB->erase(MBBI);
        MBBI = --MBBJ;
      }
      ByteCount += ByteSize;
    }
  }

  OffsetMap.clear();
  return true;
}

<commit_msg>implicit_def_vrrc doesn't generate code.<commit_after>//===-- PPCBranchSelector.cpp - Emit long conditional branches-----*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Baegeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that scans a machine function to determine which
// conditional branches need more than 16 bits of displacement to reach their
// target basic block.  It does this in two passes; a calculation of basic block
// positions pass, and a branch psuedo op to machine branch opcode pass.  This
// pass should be run last, just before the assembly printer.
//
//===----------------------------------------------------------------------===//

#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCInstrInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include <map>
using namespace llvm;

static Statistic<> NumExpanded("ppc-branch-select",
                               "Num branches expanded to long format");

namespace {
  struct VISIBILITY_HIDDEN PPCBSel : public MachineFunctionPass {
    /// OffsetMap - Mapping between BB and byte offset from start of function.
    /// TODO: replace this with a vector, using the MBB idx as the key.
    std::map<MachineBasicBlock*, unsigned> OffsetMap;

    virtual bool runOnMachineFunction(MachineFunction &Fn);

    virtual const char *getPassName() const {
      return "PowerPC Branch Selection";
    }
  };
}

/// createPPCBranchSelectionPass - returns an instance of the Branch Selection
/// Pass
///
FunctionPass *llvm::createPPCBranchSelectionPass() {
  return new PPCBSel();
}

/// getNumBytesForInstruction - Return the number of bytes of code the specified
/// instruction may be.  This returns the maximum number of bytes.
///
static unsigned getNumBytesForInstruction(MachineInstr *MI) {
  switch (MI->getOpcode()) {
  case PPC::COND_BRANCH:
    // while this will be 4 most of the time, if we emit 8 it is just a
    // minor pessimization that saves us from having to worry about
    // keeping the offsets up to date later when we emit long branch glue.
    return 8;
  case PPC::IMPLICIT_DEF_GPRC: // no asm emitted
  case PPC::IMPLICIT_DEF_G8RC: // no asm emitted
  case PPC::IMPLICIT_DEF_F4:   // no asm emitted
  case PPC::IMPLICIT_DEF_F8:   // no asm emitted
  case PPC::IMPLICIT_DEF_VRRC: // no asm emitted
    return 0;
  case PPC::INLINEASM: {       // Inline Asm: Variable size.
    MachineFunction *MF = MI->getParent()->getParent();
    const char *AsmStr = MI->getOperand(0).getSymbolName();
    return MF->getTarget().getTargetAsmInfo()->getInlineAsmLength(AsmStr);
  }
  default:
    return 4; // PowerPC instructions are all 4 bytes
  }
}

bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
  // Running total of instructions encountered since beginning of function
  unsigned ByteCount = 0;

  // For each MBB, add its offset to the offset map, and count up its
  // instructions
  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {
    MachineBasicBlock *MBB = MFI;
    OffsetMap[MBB] = ByteCount;

    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
         MBBI != EE; ++MBBI)
      ByteCount += getNumBytesForInstruction(MBBI);
  }

  // We're about to run over the MBB's again, so reset the ByteCount
  ByteCount = 0;

  // For each MBB, find the conditional branch pseudo instructions, and
  // calculate the difference between the target MBB and the current ICount
  // to decide whether or not to emit a short or long branch.
  //
  // short branch:
  // bCC .L_TARGET_MBB
  //
  // long branch:
  // bInverseCC $PC+8
  // b .L_TARGET_MBB
  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {
    MachineBasicBlock *MBB = MFI;

    for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
         MBBI != EE; ++MBBI) {
      // We may end up deleting the MachineInstr that MBBI points to, so
      // remember its opcode now so we can refer to it after calling erase()
      unsigned ByteSize = getNumBytesForInstruction(MBBI);
      if (MBBI->getOpcode() != PPC::COND_BRANCH) {
        ByteCount += ByteSize;
        continue;
      }

      // condbranch operands:
      // 0. CR register
      // 1. PPC branch opcode
      // 2. Target MBB
      MachineBasicBlock *DestMBB = MBBI->getOperand(2).getMachineBasicBlock();
      unsigned Opcode = MBBI->getOperand(1).getImmedValue();
      unsigned CRReg = MBBI->getOperand(0).getReg();

      int Displacement = OffsetMap[DestMBB] - ByteCount;
      unsigned Inverted = PPCInstrInfo::invertPPCBranchOpcode(Opcode);

      MachineBasicBlock::iterator MBBJ;
      if (Displacement >= -32768 && Displacement <= 32767) {
        MBBJ = BuildMI(*MBB, MBBJ, Opcode, 2).addReg(CRReg).addMBB(DestMBB);
      } else {
        // Long branch, skip next branch instruction (i.e. $PC+8).
        ++NumExpanded;
        BuildMI(*MBB, MBBJ, Inverted, 2).addReg(CRReg).addImm(2);
        MBBJ = BuildMI(*MBB, MBBJ, PPC::B, 1).addMBB(DestMBB);
      }

      // Erase the psuedo COND_BRANCH instruction, and then back up the
      // iterator so that when the for loop increments it, we end up in
      // the correct place rather than iterating off the end.
      MBB->erase(MBBI);
      MBBI = MBBJ;
      ByteCount += ByteSize;
    }
  }

  OffsetMap.clear();
  return true;
}

<|endoftext|>


<commit_before>/* The following code example is taken from the book
 * "The C++ Standard Library - A Tutorial and Reference, 2nd Edition"
 * by Nicolai M. Josuttis, Addison-Wesley, 2012
 *
 * (C) Copyright Nicolai M. Josuttis 2012.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */
#include "algostuff.hpp"
using namespace std;

int main()
{
    vector<int> coll = { 5, 3, 9, 1, 3, 4, 8, 2, 6 };
    PRINT_ELEMENTS(coll,"coll: ");

    // define predicate: check whether element is odd:
    auto isOdd = [](int elem) {
                     return elem%2==1;
                 };

    // check whether coll is partitioned in odd and even elements
    if (is_partitioned (coll.cbegin(), coll.cend(),  // range
                        isOdd)) {                    // predicate
        cout << "coll is partitioned" << endl;

        // find first even element:
        auto pos = partition_point (coll.cbegin(),coll.cend(),
                                    isOdd);
        cout << "first even element: " << *pos << endl;
    }
    else {
        cout << "coll is not partitioned" << endl;
    }
}
<commit_msg>test is_partitioned && partition_point<commit_after>/* The following code example is taken from the book
 * "The C++ Standard Library - A Tutorial and Reference, 2nd Edition"
 * by Nicolai M. Josuttis, Addison-Wesley, 2012
 *
 * (C) Copyright Nicolai M. Josuttis 2012.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */
#include "algostuff.hpp"
using namespace std;

int main()
{
    vector<int> coll = { 5, 3, 9, 1, 3, 4, 8, 2, 6 };
    PRINT_ELEMENTS(coll,"coll: ");

    // define predicate: check whether element is odd:
    auto isOdd = [](int elem) {
                     return elem%2==1;
                 };

    // check whether coll is partitioned in odd and even elements
    if (is_partitioned(coll.cbegin(), coll.cend(),  // range
                        isOdd)) {                   // predicate
        cout << "coll is partitioned" << endl;

        // find first even element:
        // The iterator past the end of the first partition within [first, last) or last if all elements satisfy p.
        auto pos = partition_point(coll.cbegin(),coll.cend(),
                                    isOdd);
        cout << "first even element: " << *pos << endl;
    } else {
        cout << "coll is not partitioned" << endl;
    }
}
<|endoftext|>


<commit_before>#include "SoundEngine.h"

SoundEngine::SoundEngine()
{
    sounds = new SoundManager();
}

void SoundEngine::init() {
    int flags = Mix_Init(MIX_INIT_MP3);
    SDL_assert(MIX_INIT_MP3 == flags);
    SDL_assert(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) == 0);

    SDL_Log("Sound engine loaded");
    setMusicVolumePercent(100.0f);
    SDL_Log("Music volume initialized to %d", Mix_VolumeMusic(-1));
}

SoundEngine::~SoundEngine()
{
    delete(sounds);
    Mix_CloseAudio();
}

void SoundEngine::playSound(const std::string &name, int loops) const
{
    SDL_Log("Playing %s sound", name.c_str());
    Mix_Chunk *sound = sounds->getSoundWithName(name);
    SDL_assert(sound != nullptr);
    Mix_PlayChannel(-1, sound, loops);
}

void SoundEngine::playMusic(const std::string &name, int loops) const
{
    if(Mix_PlayingMusic()) {
        SDL_Log("Halting previous music playing");
        Mix_HaltMusic();
    }
    Mix_Music *sound = sounds->getMusicWithName(name);
    SDL_assert(sound != nullptr);
    int playing = Mix_PlayMusic(sound, loops);
    SDL_Log("Playing %s music", name.c_str());
    SDL_Log("Can't play music: %s", Mix_GetError());
    if(playing == -1)
    {
        SDL_Log("Can't play music: %s", Mix_GetError());
    }
}

void SoundEngine::playMusicWithFade(const std::string &name, int fade, int loops) const
{
    Mix_Music *sound = sounds->getMusicWithName(name);
    SDL_assert(sound != nullptr);
    Mix_FadeInMusic(sound, loops, fade);
    SDL_Log("Playing %s music with fade", name.c_str());
}
<commit_msg>Removing mp3 check in the sound engine<commit_after>#include "SoundEngine.h"

SoundEngine::SoundEngine()
{
    sounds = new SoundManager();
}

void SoundEngine::init() {
    SDL_assert(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) == 0);

    SDL_Log("Sound engine loaded");
    setMusicVolumePercent(100.0f);
    SDL_Log("Music volume initialized to %d", Mix_VolumeMusic(-1));
}

SoundEngine::~SoundEngine()
{
    delete(sounds);
    Mix_CloseAudio();
}

void SoundEngine::playSound(const std::string &name, int loops) const
{
    SDL_Log("Playing %s sound", name.c_str());
    Mix_Chunk *sound = sounds->getSoundWithName(name);
    SDL_assert(sound != nullptr);
    Mix_PlayChannel(-1, sound, loops);
}

void SoundEngine::playMusic(const std::string &name, int loops) const
{
    if(Mix_PlayingMusic()) {
        SDL_Log("Halting previous music playing");
        Mix_HaltMusic();
    }
    Mix_Music *sound = sounds->getMusicWithName(name);
    SDL_assert(sound != nullptr);
    int playing = Mix_PlayMusic(sound, loops);
    SDL_Log("Playing %s music", name.c_str());
    SDL_Log("Can't play music: %s", Mix_GetError());
    if(playing == -1)
    {
        SDL_Log("Can't play music: %s", Mix_GetError());
    }
}

void SoundEngine::playMusicWithFade(const std::string &name, int fade, int loops) const
{
    Mix_Music *sound = sounds->getMusicWithName(name);
    SDL_assert(sound != nullptr);
    Mix_FadeInMusic(sound, loops, fade);
    SDL_Log("Playing %s music with fade", name.c_str());
}
<|endoftext|>


<commit_before>#include "osx_window_capture.h"

// remove the window title bar which we are not interested in
#define OSX_WINDOW_TITLE_BAR_HEIGHT 22

OSXWindowCapture::OSXWindowCapture(const string& windowName)
  :name(windowName)
{
  Update();
}

void OSXWindowCapture::Update() {
  winId = FindWindow(name);
  rect = GetWindowRect(winId);
}

int OSXWindowCapture::GetWidth() {
  return CGRectGetWidth(rect);
}

int OSXWindowCapture::GetHeight() {
  int height = CGRectGetHeight(rect);
  return IsFullscreen() ? height : max<int>(height - OSX_WINDOW_TITLE_BAR_HEIGHT, 0);
}

QPixmap OSXWindowCapture::Capture(int x, int y, int w, int h) {
  Update();

  if(!w) w = GetWidth();
  if(!w) h = GetHeight();

  CGRect captureRect = CGRectMake(x + CGRectGetMinX(rect),
      y + CGRectGetMinY(rect) + (IsFullscreen() ? 0 : OSX_WINDOW_TITLE_BAR_HEIGHT),
      w,
      h);

  CGImageRef image = CGWindowListCreateImage(captureRect,
      kCGWindowListOptionIncludingWindow,
      winId,
      kCGWindowImageNominalResolution |  kCGWindowImageBoundsIgnoreFraming);

  QPixmap pixmap = QPixmap::fromMacCGImageRef(image);

  CGImageRelease(image);

  return pixmap;
}

bool OSXWindowCapture::IsFullscreen() {
  // this is not the most elegant solution, but I couldn't find a better way
  return CGRectGetMinX(rect) == 0.0f &&
    CGRectGetMinY(rect) == 0.0f &&
    (int(CGRectGetHeight(rect)) & OSX_WINDOW_TITLE_BAR_HEIGHT) != OSX_WINDOW_TITLE_BAR_HEIGHT;
}

bool OSXWindowCapture::WindowFound() {
  Update();
  return winId != 0;
}

int OSXWindowCapture::FindWindow(const string& name) {
  int winId = 0;

  CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID);
  CFIndex numWindows = CFArrayGetCount(windowList);

  CFStringRef nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name.c_str(), kCFStringEncodingMacRoman);

  for( int i = 0; i < (int)numWindows; i++ ) {
    CFDictionaryRef info = (CFDictionaryRef)CFArrayGetValueAtIndex(windowList, i);
    CFStringRef thisWindowName = (CFStringRef)CFDictionaryGetValue(info, kCGWindowName);
    CFStringRef thisWindowOwnerName = (CFStringRef)CFDictionaryGetValue(info, kCGWindowOwnerName);
    CFNumberRef thisWindowNumber = (CFNumberRef)CFDictionaryGetValue(info, kCGWindowNumber);

    if(thisWindowOwnerName && CFStringCompare(thisWindowOwnerName, nameRef, 0) == kCFCompareEqualTo) {
      if(thisWindowName && CFStringCompare(thisWindowName, nameRef, 0) == kCFCompareEqualTo) {
        CFNumberGetValue(thisWindowNumber, kCFNumberIntType, &winId);
        break;
      }
    }
  }

  CFRelease(nameRef);

  return winId;
}

CGRect OSXWindowCapture::GetWindowRect(int windowId) {
  CGRect rect = CGRectMake(0, 0, 0, 0);

  CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionIncludingWindow, windowId);
  CFIndex numWindows = CFArrayGetCount(windowList);
  if( numWindows > 0 ) {
    CFDictionaryRef info = (CFDictionaryRef)CFArrayGetValueAtIndex(windowList, 0);
    CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)CFDictionaryGetValue(info, kCGWindowBounds), &rect);
  }

  return rect;
}
<commit_msg>disable automatic update due to performance hit<commit_after>#include "osx_window_capture.h"

// remove the window title bar which we are not interested in
#define OSX_WINDOW_TITLE_BAR_HEIGHT 22

OSXWindowCapture::OSXWindowCapture(const string& windowName)
  :name(windowName)
{
  Update();
}

void OSXWindowCapture::Update() {
  winId = FindWindow(name);
  rect = GetWindowRect(winId);
}

int OSXWindowCapture::GetWidth() {
  return CGRectGetWidth(rect);
}

int OSXWindowCapture::GetHeight() {
  int height = CGRectGetHeight(rect);
  return IsFullscreen() ? height : max<int>(height - OSX_WINDOW_TITLE_BAR_HEIGHT, 0);
}

QPixmap OSXWindowCapture::Capture(int x, int y, int w, int h) {
  if(!w) w = GetWidth();
  if(!w) h = GetHeight();

  CGRect captureRect = CGRectMake(x + CGRectGetMinX(rect),
      y + CGRectGetMinY(rect) + (IsFullscreen() ? 0 : OSX_WINDOW_TITLE_BAR_HEIGHT),
      w,
      h);

  CGImageRef image = CGWindowListCreateImage(captureRect,
      kCGWindowListOptionIncludingWindow,
      winId,
      kCGWindowImageNominalResolution |  kCGWindowImageBoundsIgnoreFraming);

  QPixmap pixmap = QPixmap::fromMacCGImageRef(image);

  CGImageRelease(image);

  return pixmap;
}

bool OSXWindowCapture::IsFullscreen() {
  // this is not the most elegant solution, but I couldn't find a better way
  return CGRectGetMinX(rect) == 0.0f &&
    CGRectGetMinY(rect) == 0.0f &&
    (int(CGRectGetHeight(rect)) & OSX_WINDOW_TITLE_BAR_HEIGHT) != OSX_WINDOW_TITLE_BAR_HEIGHT;
}

bool OSXWindowCapture::WindowFound() {
  return winId != 0;
}

int OSXWindowCapture::FindWindow(const string& name) {
  int winId = 0;

  CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID);
  CFIndex numWindows = CFArrayGetCount(windowList);

  CFStringRef nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name.c_str(), kCFStringEncodingMacRoman);

  for( int i = 0; i < (int)numWindows; i++ ) {
    CFDictionaryRef info = (CFDictionaryRef)CFArrayGetValueAtIndex(windowList, i);
    CFStringRef thisWindowName = (CFStringRef)CFDictionaryGetValue(info, kCGWindowName);
    CFStringRef thisWindowOwnerName = (CFStringRef)CFDictionaryGetValue(info, kCGWindowOwnerName);
    CFNumberRef thisWindowNumber = (CFNumberRef)CFDictionaryGetValue(info, kCGWindowNumber);

    if(thisWindowOwnerName && CFStringCompare(thisWindowOwnerName, nameRef, 0) == kCFCompareEqualTo) {
      if(thisWindowName && CFStringCompare(thisWindowName, nameRef, 0) == kCFCompareEqualTo) {
        CFNumberGetValue(thisWindowNumber, kCFNumberIntType, &winId);
        break;
      }
    }
  }

  CFRelease(nameRef);

  return winId;
}

CGRect OSXWindowCapture::GetWindowRect(int windowId) {
  CGRect rect = CGRectMake(0, 0, 0, 0);

  CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionIncludingWindow, windowId);
  CFIndex numWindows = CFArrayGetCount(windowList);
  if( numWindows > 0 ) {
    CFDictionaryRef info = (CFDictionaryRef)CFArrayGetValueAtIndex(windowList, 0);
    CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)CFDictionaryGetValue(info, kCGWindowBounds), &rect);
  }

  return rect;
}
<|endoftext|>


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

#include <cstdint>
#include <cstdio>

namespace libwebm {

std::int64_t NanosecondsTo90KhzTicks(std::int64_t nanoseconds) {
  const double kNanosecondsPerSecond = 1000000000.0;
  const double pts_seconds = nanoseconds / kNanosecondsPerSecond;
  return pts_seconds * 90000;
}

bool ParseVP9SuperFrameIndex(const std::uint8_t* frame,
                             std::size_t length,
                             Ranges* frame_ranges) {
  if (frame == nullptr || length == 0 || frame_ranges == nullptr)
    return false;

  bool parse_ok = false;
  const std::uint8_t marker = frame[length - 1];
  const std::uint32_t kHasSuperFrameIndexMask = 0xe0;
  const std::uint32_t kSuperFrameMarker = 0xc0;

  if ((marker & kHasSuperFrameIndexMask) == kSuperFrameMarker) {
    const std::uint32_t kFrameCountMask = 0x7;
    const int num_frames = (marker & kFrameCountMask) + 1;
    const int length_field_size = ((marker >> 3) & 0x3) + 1;
    const std::size_t index_length = 2 + length_field_size * num_frames;

    // Consume the super frame index.
    std::size_t frame_offset = index_length;

    if (length >= index_length && frame[length - index_length] == marker) {
      // Found a valid superframe index.
      const std::uint8_t* byte = frame + length - index_length + 1;

      for (int i = 0; i < num_frames; ++i) {
        std::uint32_t child_frame_length = 0;

        for (int j = 0; j < length_field_size; ++j) {
          child_frame_length |= (*byte++) << (j * 8);
        }

        frame_ranges->push_back(Range(frame_offset, child_frame_length));
        frame_offset += child_frame_length;
      }

      if (frame_ranges->size() != num_frames) {
        std::fprintf(stderr, "Webm2Pes: superframe index parse failed.\n");
        return false;
      }

      parse_ok = true;
    } else {
      std::fprintf(stderr, "Webm2Pes: Invalid superframe index.\n");
    }
  }
  return parse_ok;
}

bool WriteUint8(std::uint8_t val, std::FILE* fileptr) {
  if (fileptr == nullptr)
    return false;
  return (std::fputc(val, fileptr) == val);
}

}  // namespace libwebm
<commit_msg>webm2pes: Fix super frame splitting.<commit_after>// Copyright (c) 2015 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "common/libwebm_utils.h"

#include <cstdint>
#include <cstdio>

namespace libwebm {

std::int64_t NanosecondsTo90KhzTicks(std::int64_t nanoseconds) {
  const double kNanosecondsPerSecond = 1000000000.0;
  const double pts_seconds = nanoseconds / kNanosecondsPerSecond;
  return pts_seconds * 90000;
}

bool ParseVP9SuperFrameIndex(const std::uint8_t* frame,
                             std::size_t frame_length,
                             Ranges* frame_ranges) {
  if (frame == nullptr || frame_length == 0 || frame_ranges == nullptr)
    return false;

  bool parse_ok = false;
  const std::uint8_t marker = frame[frame_length - 1];
  const std::uint32_t kHasSuperFrameIndexMask = 0xe0;
  const std::uint32_t kSuperFrameMarker = 0xc0;
  const std::uint32_t kLengthFieldSizeMask = 0x3;

  if ((marker & kHasSuperFrameIndexMask) == kSuperFrameMarker) {
    const std::uint32_t kFrameCountMask = 0x7;
    const int num_frames = (marker & kFrameCountMask) + 1;
    const int length_field_size = ((marker >> 3) & kLengthFieldSizeMask) + 1;
    const std::size_t index_length = 2 + length_field_size * num_frames;

    if (frame_length < index_length) {
      std::fprintf(stderr, "Webm2Pes: Invalid superframe index size.\n");
      return false;
    }

    // Consume the super frame index. Note: it's at the end of the super frame.
    const std::size_t length = frame_length - index_length;

    if (length >= index_length &&
        frame[frame_length - index_length] == marker) {
      // Found a valid superframe index.
      const std::uint8_t* byte = frame + length + 1;

      std::size_t frame_offset = 0;
      for (int i = 0; i < num_frames; ++i) {
        std::uint32_t child_frame_length = 0;

        for (int j = 0; j < length_field_size; ++j) {
          child_frame_length |= (*byte++) << (j * 8);
        }

        frame_ranges->push_back(Range(frame_offset, child_frame_length));
        frame_offset += child_frame_length;
      }

      if (frame_ranges->size() != num_frames) {
        std::fprintf(stderr, "Webm2Pes: superframe index parse failed.\n");
        return false;
      }

      parse_ok = true;
    } else {
      std::fprintf(stderr, "Webm2Pes: Invalid superframe index.\n");
    }
  }
  return parse_ok;
}

bool WriteUint8(std::uint8_t val, std::FILE* fileptr) {
  if (fileptr == nullptr)
    return false;
  return (std::fputc(val, fileptr) == val);
}

}  // namespace libwebm
<|endoftext|>


<commit_before>#include "ui/gl/gl_implementation.h"
#include "imx_gl_viv_direct_texture.h"

bool init_viv_direct_texture(gfx::GLContext &context, GLESVIVDirectTextureProcs &procs)
{
	VLOG(1) << "Initializing Vivante direct texture GLES extension";

	gfx::GLImplementation glimpl = gfx::GetGLImplementation();
	if (glimpl != gfx::kGLImplementationEGLGLES2)
	{
		LOG(INFO) << "Cannot initialize direct textures - GL implementation is "
		          << gfx::GetGLImplementationName(glimpl)
		          << ", expected " <<
		          gfx::GetGLImplementationName(gfx::kGLImplementationEGLGLES2);
		return false;
	}

	if (context.HasExtension("GL_VIV_direct_texture"))
		VLOG(1) << "GL_VIV_direct_texture supported";
	else
	{
		VLOG(1) << "GL_VIV_direct_texture not supported";
		return false;
	}

	procs.TexDirectVIV           = reinterpret_cast < PFNGLTEXDIRECTVIVPROC >           (gfx::GetGLProcAddress("glTexDirectVIV"));
	procs.TexDirectVIVMap        = reinterpret_cast < PFNGLTEXDIRECTVIVMAPPROC >        (gfx::GetGLProcAddress("glTexDirectVIVMap"));
	procs.TexDirectTiledMapVIV   = reinterpret_cast < PFNGLTEXDIRECTTILEDMAPVIVPROC >   (gfx::GetGLProcAddress("glTexDirectTiledMapVIV"));
	procs.TexDirectInvalidateVIV = reinterpret_cast < PFNGLTEXDIRECTINVALIDATEVIVPROC > (gfx::GetGLProcAddress("glTexDirectInvalidateVIV"));

	return true;
}

<commit_msg>Let direct texture code correctly detect the extension with newer drivers<commit_after>#include "ui/gl/gl_implementation.h"
#include "imx_gl_viv_direct_texture.h"

bool init_viv_direct_texture(gfx::GLContext &context, GLESVIVDirectTextureProcs &procs)
{
	VLOG(1) << "Initializing Vivante direct texture GLES extension";

	gfx::GLImplementation glimpl = gfx::GetGLImplementation();
	if (glimpl != gfx::kGLImplementationEGLGLES2)
	{
		LOG(INFO) << "Cannot initialize direct textures - GL implementation is "
		          << gfx::GetGLImplementationName(glimpl)
		          << ", expected " <<
		          gfx::GetGLImplementationName(gfx::kGLImplementationEGLGLES2);
		return false;
	}

	// Newer Vivante drivers call the extension GL_VIV_tex_direct instead of GL_VIV_direct_texture,
	// even though it is the same extension
	if (context.HasExtension("GL_VIV_direct_texture"))
		VLOG(1) << "GL_VIV_direct_texture supported";
	else if (context.HasExtension("GL_VIV_tex_direct"))
		VLOG(1) << "GL_VIV_tex_direct supported";
	else
	{
		VLOG(1) << "Neither GL_VIV_direct_texture nor GL_VIV_tex_direct supported";
		return false;
	}

	procs.TexDirectVIV           = reinterpret_cast < PFNGLTEXDIRECTVIVPROC >           (gfx::GetGLProcAddress("glTexDirectVIV"));
	procs.TexDirectVIVMap        = reinterpret_cast < PFNGLTEXDIRECTVIVMAPPROC >        (gfx::GetGLProcAddress("glTexDirectVIVMap"));
	procs.TexDirectTiledMapVIV   = reinterpret_cast < PFNGLTEXDIRECTTILEDMAPVIVPROC >   (gfx::GetGLProcAddress("glTexDirectTiledMapVIV"));
	procs.TexDirectInvalidateVIV = reinterpret_cast < PFNGLTEXDIRECTINVALIDATEVIVPROC > (gfx::GetGLProcAddress("glTexDirectInvalidateVIV"));

	return true;
}

<|endoftext|>


<commit_before>/*++
Copyright (c) 2014 Microsoft Corporation

Module Name:

    wmax.cpp

Abstract:

    Theory based MaxSAT.

Author:

    Nikolaj Bjorner (nbjorner) 2014-4-17

Notes:

--*/
#include "wmax.h"
#include "uint_set.h"
#include "ast_pp.h"
#include "model_smt2_pp.h"
#include "smt_theory.h"
#include "smt_context.h"
#include "theory_wmaxsat.h"
#include "opt_context.h"

namespace opt {
    class maxsmt_solver_wbase : public maxsmt_solver_base {
        smt::context& ctx;
    public:
        maxsmt_solver_wbase(context& c,
                            vector<rational> const& ws, expr_ref_vector const& soft):
            maxsmt_solver_base(c, ws, soft), ctx(c.smt_context()) {}
        ~maxsmt_solver_wbase() {}

        class scoped_ensure_theory {
            smt::theory_wmaxsat* m_wth;
        public:
            scoped_ensure_theory(maxsmt_solver_wbase& s) {
                m_wth = s.ensure_theory();
            }
            ~scoped_ensure_theory() {
                m_wth->reset();
            }
            smt::theory_wmaxsat& operator()() { return *m_wth; }
        };

        smt::theory_wmaxsat* ensure_theory() {
            smt::theory_wmaxsat* wth = get_theory();
            if (wth) {
                wth->reset();
            }
            else {
                wth = alloc(smt::theory_wmaxsat, m, m_c.fm());
                ctx.register_plugin(wth);
            }
            return wth;
        }
        smt::theory_wmaxsat* get_theory() const {
            smt::theory_id th_id = m.get_family_id("weighted_maxsat");
            smt::theory* th = ctx.get_theory(th_id);
            if (th) {
                return dynamic_cast<smt::theory_wmaxsat*>(th);
            }
            else {
                return 0;
            }
        }
    };

    // ----------------------------------------------------------
    // weighted max-sat using a custom theory solver for max-sat.
    // NB. it is quite similar to pseudo-Boolean propagation.

    class wmax : public maxsmt_solver_wbase {
    public:
        wmax(context& c,
             vector<rational> const& ws, expr_ref_vector const& soft):
            maxsmt_solver_wbase(c, ws, soft) {}
        virtual ~wmax() {}

        lbool operator()() {
            TRACE("opt", tout << "weighted maxsat\n";);
            scoped_ensure_theory wth(*this);
            solver::scoped_push _s1(s());
            lbool is_sat = l_true;
            bool was_sat = false;
            for (unsigned i = 0; i < m_soft.size(); ++i) {
                wth().assert_weighted(m_soft[i].get(), m_weights[i]);
            }
            solver::scoped_push _s2(s());
            while (l_true == is_sat) {
                is_sat = s().check_sat(0,0);
                if (m_cancel) {
                    is_sat = l_undef;
                }
                if (is_sat == l_true) {
                    if (wth().is_optimal()) {
                        m_upper = wth().get_min_cost();
                        s().get_model(m_model);
                    }
                    expr_ref fml = wth().mk_block();
                    s().assert_expr(fml);
                    was_sat = true;
                }
                IF_VERBOSE(1, verbose_stream() << "(opt.wmax [" << m_lower << ":" << m_upper << "])\n";);
            }
            if (was_sat) {
                wth().get_assignment(m_assignment);
            }
            if (is_sat == l_false && was_sat) {
                is_sat = l_true;
            }
            m_upper = wth().get_min_cost();
            if (is_sat == l_true) {
                m_lower = m_upper;
            }
            TRACE("opt", tout << "min cost: " << m_upper << "\n";);
            return is_sat;
        }
    };

    maxsmt_solver_base* opt::mk_wmax(context& c,
                                     vector<rational> const& ws, expr_ref_vector const& soft) {
        return alloc(wmax, c, ws, soft);
    }

}
<commit_msg>remove extra qualifier<commit_after>/*++
Copyright (c) 2014 Microsoft Corporation

Module Name:

    wmax.cpp

Abstract:

    Theory based MaxSAT.

Author:

    Nikolaj Bjorner (nbjorner) 2014-4-17

Notes:

--*/
#include "wmax.h"
#include "uint_set.h"
#include "ast_pp.h"
#include "model_smt2_pp.h"
#include "smt_theory.h"
#include "smt_context.h"
#include "theory_wmaxsat.h"
#include "opt_context.h"

namespace opt {
    class maxsmt_solver_wbase : public maxsmt_solver_base {
        smt::context& ctx;
    public:
        maxsmt_solver_wbase(context& c,
                            vector<rational> const& ws, expr_ref_vector const& soft):
            maxsmt_solver_base(c, ws, soft), ctx(c.smt_context()) {}
        ~maxsmt_solver_wbase() {}

        class scoped_ensure_theory {
            smt::theory_wmaxsat* m_wth;
        public:
            scoped_ensure_theory(maxsmt_solver_wbase& s) {
                m_wth = s.ensure_theory();
            }
            ~scoped_ensure_theory() {
                m_wth->reset();
            }
            smt::theory_wmaxsat& operator()() { return *m_wth; }
        };

        smt::theory_wmaxsat* ensure_theory() {
            smt::theory_wmaxsat* wth = get_theory();
            if (wth) {
                wth->reset();
            }
            else {
                wth = alloc(smt::theory_wmaxsat, m, m_c.fm());
                ctx.register_plugin(wth);
            }
            return wth;
        }
        smt::theory_wmaxsat* get_theory() const {
            smt::theory_id th_id = m.get_family_id("weighted_maxsat");
            smt::theory* th = ctx.get_theory(th_id);
            if (th) {
                return dynamic_cast<smt::theory_wmaxsat*>(th);
            }
            else {
                return 0;
            }
        }
    };

    // ----------------------------------------------------------
    // weighted max-sat using a custom theory solver for max-sat.
    // NB. it is quite similar to pseudo-Boolean propagation.

    class wmax : public maxsmt_solver_wbase {
    public:
        wmax(context& c,
             vector<rational> const& ws, expr_ref_vector const& soft):
            maxsmt_solver_wbase(c, ws, soft) {}
        virtual ~wmax() {}

        lbool operator()() {
            TRACE("opt", tout << "weighted maxsat\n";);
            scoped_ensure_theory wth(*this);
            solver::scoped_push _s1(s());
            lbool is_sat = l_true;
            bool was_sat = false;
            for (unsigned i = 0; i < m_soft.size(); ++i) {
                wth().assert_weighted(m_soft[i].get(), m_weights[i]);
            }
            solver::scoped_push _s2(s());
            while (l_true == is_sat) {
                is_sat = s().check_sat(0,0);
                if (m_cancel) {
                    is_sat = l_undef;
                }
                if (is_sat == l_true) {
                    if (wth().is_optimal()) {
                        m_upper = wth().get_min_cost();
                        s().get_model(m_model);
                    }
                    expr_ref fml = wth().mk_block();
                    s().assert_expr(fml);
                    was_sat = true;
                }
                IF_VERBOSE(1, verbose_stream() << "(opt.wmax [" << m_lower << ":" << m_upper << "])\n";);
            }
            if (was_sat) {
                wth().get_assignment(m_assignment);
            }
            if (is_sat == l_false && was_sat) {
                is_sat = l_true;
            }
            m_upper = wth().get_min_cost();
            if (is_sat == l_true) {
                m_lower = m_upper;
            }
            TRACE("opt", tout << "min cost: " << m_upper << "\n";);
            return is_sat;
        }
    };

    maxsmt_solver_base* mk_wmax(context& c,
                                vector<rational> const& ws, expr_ref_vector const& soft) {
        return alloc(wmax, c, ws, soft);
    }

}
<|endoftext|>