<commit_before>#pragma once

#include <type_traits>

#define GLM_FORCE_CXX98
#include "glm/fwd.hpp"
#include "glm/gtc/quaternion.hpp"

namespace pod {
template<typename Type>
struct Vec2_template {
   Type x;
   Type y;

   operator glm::tvec2<Type>() const noexcept
   {
      return {x, y};
   }
};

using Vec2 = Vec2_template<float>;

static_assert(std::is_pod_v<Vec2>);
static_assert(sizeof(Vec2) == 8);

template<typename Type>
struct Vec3_template {
   Type x;
   Type y;
   Type z;

   operator glm::tvec3<Type>() const noexcept
   {
      return {x, y, z};
   }
};

using Vec3 = Vec3_template<float>;

static_assert(std::is_pod_v<Vec3>);
static_assert(sizeof(Vec3) == 12);

template<typename Type>
struct Vec4_template {
   Type x;
   Type y;
   Type z;
   Type w;

   operator glm::tvec4<Type>() const noexcept
   {
      return {x, y, z};
   }
};

using Vec4 = Vec4_template<float>;

static_assert(std::is_pod_v<Vec4>);
static_assert(sizeof(Vec4) == 16);

template<typename Type>
struct Mat3_template {
   Type m[9];

   operator glm::tmat3x3<Type>() const noexcept
   {
      return {m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]};
   }
};

using Mat3 = Mat3_template<float>;

static_assert(std::is_pod_v<Mat3>);
static_assert(sizeof(Mat3) == 36);

template<typename Type>
struct Quat_template {
   Type x;
   Type y;
   Type z;
   Type w;

   operator glm::tquat<Type>() const noexcept
   {
      return {w, x, y, z};
   }
};

using Quat = Quat_template<float>;

static_assert(std::is_pod_v<Quat>);
static_assert(sizeof(Quat) == 16);
}
<commit_msg>Updated glm_pod_wrappers static_asserts<commit_after>#pragma once

#include <type_traits>

#define GLM_FORCE_CXX98
#include "glm/glm.hpp"
#include "glm/gtc/quaternion.hpp"

namespace pod {
template<typename Type>
struct Vec2_template {
   Type x;
   Type y;

   operator glm::tvec2<Type>() const noexcept
   {
      return {x, y};
   }
};

using Vec2 = Vec2_template<float>;

static_assert(std::is_pod_v<Vec2>);
static_assert(sizeof(Vec2) == 8);
static_assert(sizeof(Vec2) == sizeof(glm::vec2));

template<typename Type>
struct Vec3_template {
   Type x;
   Type y;
   Type z;

   operator glm::tvec3<Type>() const noexcept
   {
      return {x, y, z};
   }
};

using Vec3 = Vec3_template<float>;

static_assert(std::is_pod_v<Vec3>);
static_assert(sizeof(Vec3) == 12);
static_assert(sizeof(Vec3) == sizeof(glm::vec3));

template<typename Type>
struct Vec4_template {
   Type x;
   Type y;
   Type z;
   Type w;

   operator glm::tvec4<Type>() const noexcept
   {
      return {x, y, z};
   }
};

using Vec4 = Vec4_template<float>;

static_assert(std::is_pod_v<Vec4>);
static_assert(sizeof(Vec4) == 16);
static_assert(sizeof(Vec4) == sizeof(glm::vec4));

template<typename Type>
struct Mat3_template {
   Type m[9];

   operator glm::tmat3x3<Type>() const noexcept
   {
      return {m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]};
   }
};

using Mat3 = Mat3_template<float>;

static_assert(std::is_pod_v<Mat3>);
static_assert(sizeof(Mat3) == 36);
static_assert(sizeof(Mat3) == sizeof(glm::mat3));

template<typename Type>
struct Quat_template {
   Type x;
   Type y;
   Type z;
   Type w;

   operator glm::tquat<Type>() const noexcept
   {
      return {w, x, y, z};
   }
};

using Quat = Quat_template<float>;

static_assert(std::is_pod_v<Quat>);
static_assert(sizeof(Quat) == 16);
static_assert(sizeof(Quat) == sizeof(glm::quat));
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * 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 "IndexerFrontendAction.h"

#include <memory>
#include <string>
#include <utility>

#include "absl/memory/memory.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
#include "kythe/cxx/common/indexing/KytheClaimClient.h"
#include "kythe/cxx/common/indexing/KytheGraphRecorder.h"
#include "kythe/cxx/common/indexing/KytheVFS.h"
#include "kythe/cxx/common/json_proto.h"
#include "kythe/cxx/common/proto_conversions.h"
#include "kythe/proto/analysis.pb.h"
#include "kythe/proto/cxx.pb.h"
#include "llvm/ADT/Twine.h"
#include "third_party/llvm/src/clang_builtin_headers.h"

#include "KytheGraphObserver.h"

namespace kythe {

bool RunToolOnCode(std::unique_ptr<clang::FrontendAction> tool_action,
                   llvm::Twine code, const std::string &filename) {
  if (tool_action == nullptr) return false;
  return clang::tooling::runToolOnCode(tool_action.release(), code, filename);
}

namespace {

bool DecodeDetails(const proto::CompilationUnit &Unit,
                   proto::CxxCompilationUnitDetails &Details) {
  for (const auto &Any : Unit.details()) {
    if (Any.type_url() == kCxxCompilationUnitDetailsURI) {
      if (UnpackAny(Any, &Details)) {
        return true;
      }
    }
  }
  return false;
}

bool DecodeHeaderSearchInfo(const proto::CxxCompilationUnitDetails &Details,
                            HeaderSearchInfo &Info) {
  if (!Details.has_header_search_info()) {
    return false;
  }
  if (!Info.CopyFrom(Details)) {
    fprintf(stderr,
            "Warning: unit has header search info, but it is ill-formed.\n");
    return false;
  }
  return true;
}

std::string ConfigureSystemHeaders(const proto::CompilationUnit &Unit,
                                   std::vector<proto::FileData> &Files) {
  std::vector<proto::FileData> OldFiles;
  OldFiles.swap(Files);
  const std::string HeaderPath = "/kythe_builtins/include/";
  std::unordered_set<std::string> NewHeaders;
  for (const auto *Header = builtin_headers_create(); Header->name != nullptr;
       ++Header) {
    auto Path = HeaderPath + Header->name;
    auto Data = Header->data;
    proto::FileData NewFile;
    NewFile.mutable_info()->set_path(Path);
    NewFile.mutable_info()->set_digest("");
    *NewFile.mutable_content() = Data;
    Files.push_back(NewFile);
    NewHeaders.insert(Path);
  }
  for (const auto &File : OldFiles) {
    if (NewHeaders.find(File.info().path()) == NewHeaders.end()) {
      Files.push_back(File);
    }
  }
  return "-resource-dir=/kythe_builtins";
}
}  // anonymous namespace

std::string IndexCompilationUnit(
    const proto::CompilationUnit &Unit, std::vector<proto::FileData> &Files,
    KytheClaimClient &Client, HashCache *Cache, KytheOutputStream &Output,
    const IndexerOptions &Options, const MetadataSupports *MetaSupports,
    const LibrarySupports *LibrarySupports,
    std::function<std::unique_ptr<IndexerWorklist>(IndexerASTVisitor *)>
        CreateWorklist) {
  HeaderSearchInfo HSI;
  proto::CxxCompilationUnitDetails Details;
  bool HSIValid = false;
  std::vector<llvm::StringRef> Dirs;
  if (DecodeDetails(Unit, Details)) {
    HSIValid = DecodeHeaderSearchInfo(Details, HSI);
    for (const auto &stat_path : Details.stat_path()) {
      Dirs.push_back(ToStringRef(stat_path.path()));
    }
  }
  std::string FixupArgument = ConfigureSystemHeaders(Unit, Files);
  if (HSIValid) {
    FixupArgument.clear();
  }
  clang::FileSystemOptions FSO;
  FSO.WorkingDir = Options.EffectiveWorkingDirectory;
  for (auto &Path : HSI.paths) {
    Dirs.push_back(ToStringRef(Path.path));
  }
  llvm::IntrusiveRefCntPtr<IndexVFS> VFS(
      new IndexVFS(FSO.WorkingDir, Files, Dirs));
  KytheGraphRecorder Recorder(&Output);
  KytheGraphObserver Observer(&Recorder, &Client, MetaSupports, VFS,
                              Options.ReportProfileEvent);
  if (Cache != nullptr) {
    Output.UseHashCache(Cache);
    Observer.StopDeferringNodes();
  }
  if (Options.DropInstantiationIndependentData) {
    Observer.DropRedundantWraiths();
  }
  Observer.set_claimant(Unit.v_name());
  Observer.set_starting_context(Unit.entry_context());
  for (const auto &Input : Unit.required_input()) {
    if (Input.has_info() && !Input.info().path().empty() &&
        Input.has_v_name()) {
      VFS->SetVName(Input.info().path(), Input.v_name());
    }
    const std::string &FilePath = Input.info().path();
    for (const auto &Row : Input.context().row()) {
      if (Row.always_process()) {
        auto ClaimableVname = Input.v_name();
        ClaimableVname.set_signature(Row.source_context() +
                                     ClaimableVname.signature());
        Client.AssignClaim(ClaimableVname, Unit.v_name());
      }
      for (const auto &Col : Row.column()) {
        Observer.AddContextInformation(FilePath, Row.source_context(),
                                       Col.offset(), Col.linked_context());
      }
    }
  }
  if (MetaSupports != nullptr) {
    MetaSupports->UseVNameLookup(
        [VFS](const std::string &path, proto::VName *out) {
          return VFS->get_vname(path, out);
        });
  }
  std::unique_ptr<IndexerFrontendAction> Action =
      absl::make_unique<IndexerFrontendAction>(
          &Observer, HSIValid ? &HSI : nullptr, Options.ShouldStopIndexing,
          std::move(CreateWorklist), LibrarySupports);
  Action->setIgnoreUnimplemented(Options.UnimplementedBehavior);
  Action->setTemplateMode(Options.TemplateBehavior);
  Action->setVerbosity(Options.Verbosity);
  llvm::IntrusiveRefCntPtr<clang::FileManager> FileManager(
      new clang::FileManager(FSO, Options.AllowFSAccess ? nullptr : VFS));
  std::vector<std::string> Args(Unit.argument().begin(), Unit.argument().end());
  Args.insert(Args.begin() + 1, "-fsyntax-only");
  Args.insert(Args.begin() + 1, "-w");
  if (!FixupArgument.empty()) {
    Args.insert(Args.begin() + 1, FixupArgument);
  }
  // StdinAdjustSingleFrontendActionFactory takes ownership of its action.
  std::unique_ptr<StdinAdjustSingleFrontendActionFactory> Tool =
      absl::make_unique<StdinAdjustSingleFrontendActionFactory>(
          std::move(Action));
  // ToolInvocation doesn't take ownership of ToolActions.
  clang::tooling::ToolInvocation Invocation(
      Args, Tool.get(), FileManager.get(),
      std::make_shared<clang::PCHContainerOperations>());
  ProfileBlock block(Observer.getProfilingCallback(), "run_invocation");
  if (!Invocation.run()) {
    return "Errors during indexing.";
  }
  return "";
}

}  // namespace kythe
<commit_msg>Compile CUDA even if we can't link<commit_after>/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * 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 "IndexerFrontendAction.h"

#include <memory>
#include <string>
#include <utility>

#include "absl/memory/memory.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
#include "kythe/cxx/common/indexing/KytheClaimClient.h"
#include "kythe/cxx/common/indexing/KytheGraphRecorder.h"
#include "kythe/cxx/common/indexing/KytheVFS.h"
#include "kythe/cxx/common/json_proto.h"
#include "kythe/cxx/common/proto_conversions.h"
#include "kythe/proto/analysis.pb.h"
#include "kythe/proto/cxx.pb.h"
#include "llvm/ADT/Twine.h"
#include "third_party/llvm/src/clang_builtin_headers.h"

#include "KytheGraphObserver.h"

namespace kythe {

bool RunToolOnCode(std::unique_ptr<clang::FrontendAction> tool_action,
                   llvm::Twine code, const std::string &filename) {
  if (tool_action == nullptr) return false;
  return clang::tooling::runToolOnCode(tool_action.release(), code, filename);
}

namespace {

bool DecodeDetails(const proto::CompilationUnit &Unit,
                   proto::CxxCompilationUnitDetails &Details) {
  for (const auto &Any : Unit.details()) {
    if (Any.type_url() == kCxxCompilationUnitDetailsURI) {
      if (UnpackAny(Any, &Details)) {
        return true;
      }
    }
  }
  return false;
}

bool DecodeHeaderSearchInfo(const proto::CxxCompilationUnitDetails &Details,
                            HeaderSearchInfo &Info) {
  if (!Details.has_header_search_info()) {
    return false;
  }
  if (!Info.CopyFrom(Details)) {
    fprintf(stderr,
            "Warning: unit has header search info, but it is ill-formed.\n");
    return false;
  }
  return true;
}

std::string ConfigureSystemHeaders(const proto::CompilationUnit &Unit,
                                   std::vector<proto::FileData> &Files) {
  std::vector<proto::FileData> OldFiles;
  OldFiles.swap(Files);
  const std::string HeaderPath = "/kythe_builtins/include/";
  std::unordered_set<std::string> NewHeaders;
  for (const auto *Header = builtin_headers_create(); Header->name != nullptr;
       ++Header) {
    auto Path = HeaderPath + Header->name;
    auto Data = Header->data;
    proto::FileData NewFile;
    NewFile.mutable_info()->set_path(Path);
    NewFile.mutable_info()->set_digest("");
    *NewFile.mutable_content() = Data;
    Files.push_back(NewFile);
    NewHeaders.insert(Path);
  }
  for (const auto &File : OldFiles) {
    if (NewHeaders.find(File.info().path()) == NewHeaders.end()) {
      Files.push_back(File);
    }
  }
  return "-resource-dir=/kythe_builtins";
}
}  // anonymous namespace

std::string IndexCompilationUnit(
    const proto::CompilationUnit &Unit, std::vector<proto::FileData> &Files,
    KytheClaimClient &Client, HashCache *Cache, KytheOutputStream &Output,
    const IndexerOptions &Options, const MetadataSupports *MetaSupports,
    const LibrarySupports *LibrarySupports,
    std::function<std::unique_ptr<IndexerWorklist>(IndexerASTVisitor *)>
        CreateWorklist) {
  HeaderSearchInfo HSI;
  proto::CxxCompilationUnitDetails Details;
  bool HSIValid = false;
  std::vector<llvm::StringRef> Dirs;
  if (DecodeDetails(Unit, Details)) {
    HSIValid = DecodeHeaderSearchInfo(Details, HSI);
    for (const auto &stat_path : Details.stat_path()) {
      Dirs.push_back(ToStringRef(stat_path.path()));
    }
  }
  std::string FixupArgument = ConfigureSystemHeaders(Unit, Files);
  if (HSIValid) {
    FixupArgument.clear();
  }
  clang::FileSystemOptions FSO;
  FSO.WorkingDir = Options.EffectiveWorkingDirectory;
  for (auto &Path : HSI.paths) {
    Dirs.push_back(ToStringRef(Path.path));
  }
  llvm::IntrusiveRefCntPtr<IndexVFS> VFS(
      new IndexVFS(FSO.WorkingDir, Files, Dirs));
  KytheGraphRecorder Recorder(&Output);
  KytheGraphObserver Observer(&Recorder, &Client, MetaSupports, VFS,
                              Options.ReportProfileEvent);
  if (Cache != nullptr) {
    Output.UseHashCache(Cache);
    Observer.StopDeferringNodes();
  }
  if (Options.DropInstantiationIndependentData) {
    Observer.DropRedundantWraiths();
  }
  Observer.set_claimant(Unit.v_name());
  Observer.set_starting_context(Unit.entry_context());
  for (const auto &Input : Unit.required_input()) {
    if (Input.has_info() && !Input.info().path().empty() &&
        Input.has_v_name()) {
      VFS->SetVName(Input.info().path(), Input.v_name());
    }
    const std::string &FilePath = Input.info().path();
    for (const auto &Row : Input.context().row()) {
      if (Row.always_process()) {
        auto ClaimableVname = Input.v_name();
        ClaimableVname.set_signature(Row.source_context() +
                                     ClaimableVname.signature());
        Client.AssignClaim(ClaimableVname, Unit.v_name());
      }
      for (const auto &Col : Row.column()) {
        Observer.AddContextInformation(FilePath, Row.source_context(),
                                       Col.offset(), Col.linked_context());
      }
    }
  }
  if (MetaSupports != nullptr) {
    MetaSupports->UseVNameLookup(
        [VFS](const std::string &path, proto::VName *out) {
          return VFS->get_vname(path, out);
        });
  }
  std::unique_ptr<IndexerFrontendAction> Action =
      absl::make_unique<IndexerFrontendAction>(
          &Observer, HSIValid ? &HSI : nullptr, Options.ShouldStopIndexing,
          std::move(CreateWorklist), LibrarySupports);
  Action->setIgnoreUnimplemented(Options.UnimplementedBehavior);
  Action->setTemplateMode(Options.TemplateBehavior);
  Action->setVerbosity(Options.Verbosity);
  llvm::IntrusiveRefCntPtr<clang::FileManager> FileManager(
      new clang::FileManager(FSO, Options.AllowFSAccess ? nullptr : VFS));
  std::vector<std::string> Args(Unit.argument().begin(), Unit.argument().end());
  Args.insert(Args.begin() + 1, "-fsyntax-only");
  Args.insert(Args.begin() + 1, "-w");
  Args.insert(Args.begin() + 1, "-nocudalib");
  if (!FixupArgument.empty()) {
    Args.insert(Args.begin() + 1, FixupArgument);
  }
  // StdinAdjustSingleFrontendActionFactory takes ownership of its action.
  std::unique_ptr<StdinAdjustSingleFrontendActionFactory> Tool =
      absl::make_unique<StdinAdjustSingleFrontendActionFactory>(
          std::move(Action));
  // ToolInvocation doesn't take ownership of ToolActions.
  clang::tooling::ToolInvocation Invocation(
      Args, Tool.get(), FileManager.get(),
      std::make_shared<clang::PCHContainerOperations>());
  ProfileBlock block(Observer.getProfilingCallback(), "run_invocation");
  if (!Invocation.run()) {
    return "Errors during indexing.";
  }
  return "";
}

}  // namespace kythe
<|endoftext|>


<commit_before>//===- DataStructureAA.cpp - Data Structure Based Alias Analysis ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass uses the top-down data structure graphs to implement a simple
// context sensitive alias analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
using namespace llvm;

namespace {
  class DSAA : public ModulePass, public AliasAnalysis {
    TDDataStructures *TD;
    BUDataStructures *BU;
  public:
    DSAA() : TD(0) {}

    //------------------------------------------------
    // Implement the Pass API
    //

    // run - Build up the result graph, representing the pointer graph for the
    // program.
    //
    bool runOnModule(Module &M) {
      InitializeAliasAnalysis(this);
      TD = &getAnalysis<TDDataStructures>();
      BU = &getAnalysis<BUDataStructures>();
      return false;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AliasAnalysis::getAnalysisUsage(AU);
      AU.setPreservesAll();                         // Does not transform code
      AU.addRequiredTransitive<TDDataStructures>(); // Uses TD Datastructures
      AU.addRequiredTransitive<BUDataStructures>(); // Uses BU Datastructures
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //

    AliasResult alias(const Value *V1, unsigned V1Size,
                      const Value *V2, unsigned V2Size);

    ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
    ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) {
      return AliasAnalysis::getModRefInfo(CS1,CS2);
    }

    virtual void deleteValue(Value *V) {
      BU->deleteValue(V);
      TD->deleteValue(V);
    }

    virtual void copyValue(Value *From, Value *To) {
      if (From == To) return;
      BU->copyValue(From, To);
      TD->copyValue(From, To);
    }

  private:
    DSGraph *getGraphForValue(const Value *V);
  };

  // Register the pass...
  RegisterOpt<DSAA> X("ds-aa", "Data Structure Graph Based Alias Analysis");

  // Register as an implementation of AliasAnalysis
  RegisterAnalysisGroup<AliasAnalysis, DSAA> Y;
}

ModulePass *llvm::createDSAAPass() { return new DSAA(); }

// getGraphForValue - Return the DSGraph to use for queries about the specified
// value...
//
DSGraph *DSAA::getGraphForValue(const Value *V) {
  if (const Instruction *I = dyn_cast<Instruction>(V))
    return &TD->getDSGraph(*I->getParent()->getParent());
  else if (const Argument *A = dyn_cast<Argument>(V))
    return &TD->getDSGraph(*A->getParent());
  else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
    return &TD->getDSGraph(*BB->getParent());
  return 0;
}

AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size,
                                       const Value *V2, unsigned V2Size) {
  if (V1 == V2) return MustAlias;

  DSGraph *G1 = getGraphForValue(V1);
  DSGraph *G2 = getGraphForValue(V2);
  assert((!G1 || !G2 || G1 == G2) && "Alias query for 2 different functions?");

  // Get the graph to use...
  DSGraph &G = *(G1 ? G1 : (G2 ? G2 : &TD->getGlobalsGraph()));

  const DSGraph::ScalarMapTy &GSM = G.getScalarMap();
  DSGraph::ScalarMapTy::const_iterator I = GSM.find((Value*)V1);
  if (I == GSM.end()) return NoAlias;

  DSGraph::ScalarMapTy::const_iterator J = GSM.find((Value*)V2);
  if (J == GSM.end()) return NoAlias;

  DSNode  *N1 = I->second.getNode(),  *N2 = J->second.getNode();
  unsigned O1 = I->second.getOffset(), O2 = J->second.getOffset();
  if (N1 == 0 || N2 == 0)
    return MayAlias;  // Can't tell whether anything aliases null.

  // We can only make a judgment of one of the nodes is complete...
  if (N1->isComplete() || N2->isComplete()) {
    if (N1 != N2)
      return NoAlias;   // Completely different nodes.

    // See if they point to different offsets...  if so, we may be able to
    // determine that they do not alias...
    if (O1 != O2) {
      if (O2 < O1) {    // Ensure that O1 <= O2
        std::swap(V1, V2);
        std::swap(O1, O2);
        std::swap(V1Size, V2Size);
      }

      if (O1+V1Size <= O2)
        return NoAlias;
    }
  }

  // FIXME: we could improve on this by checking the globals graph for aliased
  // global queries...
  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}

/// getModRefInfo - does a callsite modify or reference a value?
///
AliasAnalysis::ModRefResult
DSAA::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
  AliasAnalysis::ModRefResult Result =AliasAnalysis::getModRefInfo(CS, P, Size);
  Function *F = CS.getCalledFunction();

  if (!F || Result == NoModRef)
    return Result;

  if (F->isExternal()) {
    // If we are calling an external function, and if this global doesn't escape
    // the portion of the program we have analyzed, we can draw conclusions
    // based on whether the global escapes the program.
    Function *Caller = CS.getInstruction()->getParent()->getParent();
    DSGraph *G = &TD->getDSGraph(*Caller);
    DSScalarMap::iterator NI = G->getScalarMap().find(P);
    if (NI == G->getScalarMap().end()) {
      // If it wasn't in the local function graph, check the global graph.  This
      // can occur for globals who are locally reference but hoisted out to the
      // globals graph despite that.
      G = G->getGlobalsGraph();
      NI = G->getScalarMap().find(P);
      if (NI == G->getScalarMap().end())
        return Result;
    }

    // If we found a node and it's complete, it cannot be passed out to the
    // called function.
    if (NI->second.getNode()->isComplete())
      return NoModRef;
    return Result;
  }

  // Get the graphs for the callee and caller.  Note that we want the BU graph
  // for the callee because we don't want all caller's effects incorporated!
  const Function *Caller = CS.getInstruction()->getParent()->getParent();
  DSGraph &CallerTDGraph = TD->getDSGraph(*Caller);
  DSGraph &CalleeBUGraph = BU->getDSGraph(*F);

  // Figure out which node in the TD graph this pointer corresponds to.
  DSScalarMap &CallerSM = CallerTDGraph.getScalarMap();
  DSScalarMap::iterator NI = CallerSM.find(P);
  if (NI == CallerSM.end()) {
    if (isa<ConstantPointerNull>(P) || isa<UndefValue>(P))
      Result = NoModRef;                 // null is never modified :)
    else {
      assert(isa<GlobalVariable>(P) &&
    cast<GlobalVariable>(P)->getType()->getElementType()->isFirstClassType() &&
             "This isn't a global that DSA inconsiderately dropped "
             "from the graph?");

      DSGraph &GG = *CallerTDGraph.getGlobalsGraph();
      DSScalarMap::iterator NI = GG.getScalarMap().find(P);
      if (NI != GG.getScalarMap().end() && !NI->second.isNull()) {
        // Otherwise, if the node is only M or R, return this.  This can be
        // useful for globals that should be marked const but are not.
        DSNode *N = NI->second.getNode();
        if (!N->isModified())
          Result = (ModRefResult)(Result & ~Mod);
        if (!N->isRead())
          Result = (ModRefResult)(Result & ~Ref);
      }
    }
    return Result;
  }

  const DSNode *N = NI->second.getNode();
  assert(N && "Null pointer in scalar map??");

  // Compute the mapping from nodes in the callee graph to the nodes in the
  // caller graph for this call site.
  DSGraph::NodeMapTy CalleeCallerMap;
  DSCallSite DSCS = CallerTDGraph.getDSCallSiteForCallSite(CS);
  CallerTDGraph.computeCalleeCallerMapping(DSCS, *F, CalleeBUGraph,
                                           CalleeCallerMap);

  // Loop over all of the nodes in the callee that correspond to "N", keeping
  // track of aggregate mod/ref info.
  bool NeverReads = true, NeverWrites = true;
  for (DSGraph::NodeMapTy::iterator I = CalleeCallerMap.begin(),
         E = CalleeCallerMap.end(); I != E; ++I)
    if (I->second.getNode() == N) {
      if (I->first->isModified())
        NeverWrites = false;
      if (I->first->isRead())
        NeverReads = false;
      if (NeverReads == false && NeverWrites == false)
        return Result;
    }

  if (NeverWrites)      // We proved it was not modified.
    Result = ModRefResult(Result & ~Mod);
  if (NeverReads)       // We proved it was not read.
    Result = ModRefResult(Result & ~Ref);

  return Result;
}
<commit_msg>Cache mapping information for a call site after computing it for a mod/ref query.  If the next mod/ref query happens to be for the same call site (which is extremely likely), use the cache instead of recomputing the callee/caller mapping.  This makes -aa-eval ***MUCH*** faster with ds-aa<commit_after>//===- DataStructureAA.cpp - Data Structure Based Alias Analysis ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass uses the top-down data structure graphs to implement a simple
// context sensitive alias analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
using namespace llvm;

namespace {
  class DSAA : public ModulePass, public AliasAnalysis {
    TDDataStructures *TD;
    BUDataStructures *BU;

    // These members are used to cache mod/ref information to make us return
    // results faster, particularly for aa-eval.  On the first request of
    // mod/ref information for a particular call site, we compute and store the
    // calculated nodemap for the call site.  Any time DSA info is updated we
    // free this information, and when we move onto a new call site, this
    // information is also freed.
    CallSite MapCS;
    std::multimap<DSNode*, const DSNode*> CallerCalleeMap;
  public:
    DSAA() : TD(0) {}
    ~DSAA() {
      InvalidateCache();
    }

    void InvalidateCache() {
      MapCS = CallSite();
      CallerCalleeMap.clear();
    }

    //------------------------------------------------
    // Implement the Pass API
    //

    // run - Build up the result graph, representing the pointer graph for the
    // program.
    //
    bool runOnModule(Module &M) {
      InitializeAliasAnalysis(this);
      TD = &getAnalysis<TDDataStructures>();
      BU = &getAnalysis<BUDataStructures>();
      return false;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AliasAnalysis::getAnalysisUsage(AU);
      AU.setPreservesAll();                         // Does not transform code
      AU.addRequiredTransitive<TDDataStructures>(); // Uses TD Datastructures
      AU.addRequiredTransitive<BUDataStructures>(); // Uses BU Datastructures
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //

    AliasResult alias(const Value *V1, unsigned V1Size,
                      const Value *V2, unsigned V2Size);

    ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
    ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) {
      return AliasAnalysis::getModRefInfo(CS1,CS2);
    }

    virtual void deleteValue(Value *V) {
      InvalidateCache();
      BU->deleteValue(V);
      TD->deleteValue(V);
    }

    virtual void copyValue(Value *From, Value *To) {
      if (From == To) return;
      InvalidateCache();
      BU->copyValue(From, To);
      TD->copyValue(From, To);
    }

  private:
    DSGraph *getGraphForValue(const Value *V);
  };

  // Register the pass...
  RegisterOpt<DSAA> X("ds-aa", "Data Structure Graph Based Alias Analysis");

  // Register as an implementation of AliasAnalysis
  RegisterAnalysisGroup<AliasAnalysis, DSAA> Y;
}

ModulePass *llvm::createDSAAPass() { return new DSAA(); }

// getGraphForValue - Return the DSGraph to use for queries about the specified
// value...
//
DSGraph *DSAA::getGraphForValue(const Value *V) {
  if (const Instruction *I = dyn_cast<Instruction>(V))
    return &TD->getDSGraph(*I->getParent()->getParent());
  else if (const Argument *A = dyn_cast<Argument>(V))
    return &TD->getDSGraph(*A->getParent());
  else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
    return &TD->getDSGraph(*BB->getParent());
  return 0;
}

AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size,
                                       const Value *V2, unsigned V2Size) {
  if (V1 == V2) return MustAlias;

  DSGraph *G1 = getGraphForValue(V1);
  DSGraph *G2 = getGraphForValue(V2);
  assert((!G1 || !G2 || G1 == G2) && "Alias query for 2 different functions?");

  // Get the graph to use...
  DSGraph &G = *(G1 ? G1 : (G2 ? G2 : &TD->getGlobalsGraph()));

  const DSGraph::ScalarMapTy &GSM = G.getScalarMap();
  DSGraph::ScalarMapTy::const_iterator I = GSM.find((Value*)V1);
  if (I == GSM.end()) return NoAlias;

  DSGraph::ScalarMapTy::const_iterator J = GSM.find((Value*)V2);
  if (J == GSM.end()) return NoAlias;

  DSNode  *N1 = I->second.getNode(),  *N2 = J->second.getNode();
  unsigned O1 = I->second.getOffset(), O2 = J->second.getOffset();
  if (N1 == 0 || N2 == 0)
    return MayAlias;  // Can't tell whether anything aliases null.

  // We can only make a judgment of one of the nodes is complete...
  if (N1->isComplete() || N2->isComplete()) {
    if (N1 != N2)
      return NoAlias;   // Completely different nodes.

    // See if they point to different offsets...  if so, we may be able to
    // determine that they do not alias...
    if (O1 != O2) {
      if (O2 < O1) {    // Ensure that O1 <= O2
        std::swap(V1, V2);
        std::swap(O1, O2);
        std::swap(V1Size, V2Size);
      }

      if (O1+V1Size <= O2)
        return NoAlias;
    }
  }

  // FIXME: we could improve on this by checking the globals graph for aliased
  // global queries...
  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}

/// getModRefInfo - does a callsite modify or reference a value?
///
AliasAnalysis::ModRefResult
DSAA::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
  DSNode *N = 0;
  // First step, check our cache.
  if (CS.getInstruction() == MapCS.getInstruction()) {
    {
      const Function *Caller = CS.getInstruction()->getParent()->getParent();
      DSGraph &CallerTDGraph = TD->getDSGraph(*Caller);

      // Figure out which node in the TD graph this pointer corresponds to.
      DSScalarMap &CallerSM = CallerTDGraph.getScalarMap();
      DSScalarMap::iterator NI = CallerSM.find(P);
      if (NI == CallerSM.end()) {
        InvalidateCache();
        return DSAA::getModRefInfo(CS, P, Size);
      }
      N = NI->second.getNode();
    }

  HaveMappingInfo:
    assert(N && "Null pointer in scalar map??");

    typedef std::multimap<DSNode*, const DSNode*>::iterator NodeMapIt;
    std::pair<NodeMapIt, NodeMapIt> Range = CallerCalleeMap.equal_range(N);

    // Loop over all of the nodes in the callee that correspond to "N", keeping
    // track of aggregate mod/ref info.
    bool NeverReads = true, NeverWrites = true;
    for (; Range.first != Range.second; ++Range.first) {
      if (Range.first->second->isModified())
        NeverWrites = false;
      if (Range.first->second->isRead())
        NeverReads = false;
      if (NeverReads == false && NeverWrites == false)
        return AliasAnalysis::getModRefInfo(CS, P, Size);
    }

    ModRefResult Result = ModRef;
    if (NeverWrites)      // We proved it was not modified.
      Result = ModRefResult(Result & ~Mod);
    if (NeverReads)       // We proved it was not read.
      Result = ModRefResult(Result & ~Ref);

    return ModRefResult(Result & AliasAnalysis::getModRefInfo(CS, P, Size));
  }

  // Any cached info we have is for the wrong function.
  InvalidateCache();

  Function *F = CS.getCalledFunction();

  if (!F) return AliasAnalysis::getModRefInfo(CS, P, Size);

  if (F->isExternal()) {
    // If we are calling an external function, and if this global doesn't escape
    // the portion of the program we have analyzed, we can draw conclusions
    // based on whether the global escapes the program.
    Function *Caller = CS.getInstruction()->getParent()->getParent();
    DSGraph *G = &TD->getDSGraph(*Caller);
    DSScalarMap::iterator NI = G->getScalarMap().find(P);
    if (NI == G->getScalarMap().end()) {
      // If it wasn't in the local function graph, check the global graph.  This
      // can occur for globals who are locally reference but hoisted out to the
      // globals graph despite that.
      G = G->getGlobalsGraph();
      NI = G->getScalarMap().find(P);
      if (NI == G->getScalarMap().end())
        return AliasAnalysis::getModRefInfo(CS, P, Size);
    }

    // If we found a node and it's complete, it cannot be passed out to the
    // called function.
    if (NI->second.getNode()->isComplete())
      return NoModRef;
    return AliasAnalysis::getModRefInfo(CS, P, Size);
  }

  // Get the graphs for the callee and caller.  Note that we want the BU graph
  // for the callee because we don't want all caller's effects incorporated!
  const Function *Caller = CS.getInstruction()->getParent()->getParent();
  DSGraph &CallerTDGraph = TD->getDSGraph(*Caller);
  DSGraph &CalleeBUGraph = BU->getDSGraph(*F);

  // Figure out which node in the TD graph this pointer corresponds to.
  DSScalarMap &CallerSM = CallerTDGraph.getScalarMap();
  DSScalarMap::iterator NI = CallerSM.find(P);
  if (NI == CallerSM.end()) {
    ModRefResult Result = ModRef;
    if (isa<ConstantPointerNull>(P) || isa<UndefValue>(P))
      return NoModRef;                 // null is never modified :)
    else {
      assert(isa<GlobalVariable>(P) &&
    cast<GlobalVariable>(P)->getType()->getElementType()->isFirstClassType() &&
             "This isn't a global that DSA inconsiderately dropped "
             "from the graph?");

      DSGraph &GG = *CallerTDGraph.getGlobalsGraph();
      DSScalarMap::iterator NI = GG.getScalarMap().find(P);
      if (NI != GG.getScalarMap().end() && !NI->second.isNull()) {
        // Otherwise, if the node is only M or R, return this.  This can be
        // useful for globals that should be marked const but are not.
        DSNode *N = NI->second.getNode();
        if (!N->isModified())
          Result = (ModRefResult)(Result & ~Mod);
        if (!N->isRead())
          Result = (ModRefResult)(Result & ~Ref);
      }
    }

    if (Result == NoModRef) return Result;
    return ModRefResult(Result & AliasAnalysis::getModRefInfo(CS, P, Size));
  }

  // Compute the mapping from nodes in the callee graph to the nodes in the
  // caller graph for this call site.
  DSGraph::NodeMapTy CalleeCallerMap;
  DSCallSite DSCS = CallerTDGraph.getDSCallSiteForCallSite(CS);
  CallerTDGraph.computeCalleeCallerMapping(DSCS, *F, CalleeBUGraph,
                                           CalleeCallerMap);

  // Remember the mapping and the call site for future queries.
  MapCS = CS;

  // Invert the mapping into CalleeCallerInvMap.
  for (DSGraph::NodeMapTy::iterator I = CalleeCallerMap.begin(),
         E = CalleeCallerMap.end(); I != E; ++I)
    CallerCalleeMap.insert(std::make_pair(I->second.getNode(), I->first));

  N = NI->second.getNode();
  goto HaveMappingInfo;
}
<|endoftext|>


<commit_before>/* * * * * * * * * * * * *\
|*             ╔═╗ v0.3  *|
|* ╔═╦═╦═══╦═══╣ ╚═╦═╦═╗ *|
|* ║ ╔═╣ '╔╬═╗╚╣ ║ ║  '║ *|
|* ╚═╝ ╚═══╩═══╩═╩═╣ ╔═╝ *|
|* * * * * * * * * ╚═╝ * *|
|* Manipulation tool for *|
|*    ESRI Shapefiles    *|
|* * * * * * * * * * * * *|
|* http://www.npolar.no/ *|
\* * * * * * * * * * * * */

#include "../handler.hpp"
#include "../polygon.hpp"
#include "../shx.hpp"

#include <vector>
#include <cstdio>

namespace reshp
{
    void handler::subtract(const std::string& basefile, const std::string& maskfile, const char* outputfile)
    {
        if(verbose_)
            printf("subtract '%s' from '%s'\n", maskfile.c_str(), basefile.c_str());

        reshp::shp base, mask;

        if(verbose_)
            printf("  loading base shapefile '%s'\n", basefile.c_str());

        if(!base.load(basefile))
            return;

        if(verbose_)
            printf("  loading mask shapefile '%s'\n", maskfile.c_str());

        if(!mask.load(maskfile))
            return;

        std::vector<reshp::polygon> basepolys, maskpolys;

        if(verbose_)
            printf("  converting base shapefile polygons\n");

        for(unsigned r = 0; r < base.records.size(); ++r)
        {
            reshp::shp::record& record = base.records[r];

            if(record.type != reshp::shp::shape::polygon)
            {
                printf("    shapefile record type not supported as base shape for subtraction: %s\n", reshp::shp::typestr(record.type));
                continue;
            }

            if(!record.polygon)
            {
                printf("    missing polygon data in base shapefile: %s (record #%i)\n", basefile.c_str(), record.number);
                continue;
            }

            reshp::polygon poly(*record.polygon);
            basepolys.push_back(poly);
        }

        if(verbose_)
            printf("  converting mask shapefile polygons\n");

        for(unsigned r = 0; r < mask.records.size(); ++r)
        {
            reshp::shp::record& record = mask.records[r];

            if(record.type != reshp::shp::shape::polygon)
            {
                printf("    shapefile record type not supported as mask shape for subtraction: %s\n", reshp::shp::typestr(record.type));
                continue;
            }

            if(!record.polygon)
            {
                printf("    missing polygon data in mask shapefile: %s (record #%i)\n", maskfile.c_str(), record.number);
                continue;
            }

            reshp::polygon poly(*record.polygon);
            maskpolys.push_back(poly);
        }

        if(verbose_)
            printf("  testing collision in %lu polygons\n", basepolys.size() * maskpolys.size());

        for(unsigned bpoly = 0; bpoly < basepolys.size(); ++bpoly)
        {
            for(unsigned mpoly = 0; mpoly < maskpolys.size(); ++mpoly)
            {
                // Mask polygon is entirely inside base polygon
                if(maskpolys[mpoly].inside(basepolys[bpoly]))
                {
                    if(verbose_)
                        printf("    mask polygon #%u is entirely inside base polygon #%u\n", mpoly, bpoly);

                    for(unsigned r = 0; r < maskpolys[mpoly].rings.size(); ++ r)
                    {
                        if(maskpolys[mpoly].rings[r].type == reshp::polygon::ring::outer)
                        {
                            if(verbose_)
                                printf("      outer ring #%u added to base polygon as inner ring\n", r);

                            basepolys[bpoly].rings.push_back(maskpolys[mpoly].rings[r]);
                            basepolys[bpoly].rings.back().type = reshp::polygon::ring::inner;
                        }
                        else printf("      ignored inner ring #%u in mask polygon\n", r);
                    }

                    continue;
                }

                std::vector<reshp::polygon::intersection> intersections;
                std::vector<reshp::polygon::ring> rings;

                // Mask polygon intersects base polygon
                if(maskpolys[mpoly].intersects(basepolys[bpoly], &intersections))
                {
                    if(verbose_)
                        printf("    %lu intersections found between base polygon #%u and mask polygon #%u:\n", intersections.size(), bpoly, mpoly);

                    for(unsigned i = 0; i < intersections.size(); ++i)
                    {
                        if(verbose_)
                            printf("      [%8.4f, %8.4f]\n", intersections[i].point.x, intersections[i].point.y);

                        if(basepolys[bpoly].contains(intersections[i].segment->start))
                        {
                            bool done = false;
                            reshp::polygon::ring ring; // outer by default

                            for(unsigned n = 0, s = intersections[i].segment_index; !done && n < intersections[i].ring->segments.size(); ++n)
                            {
                                int tindex = -1;
                                reshp::point intersection;
                                reshp::segment segment((n ? intersections[i].ring->segments[s].end : intersections[i].point), intersections[i].ring->segments[s].start);

                                for(unsigned t = 0; n && t < intersections[i].intersector.ring->segments.size(); ++t)
                                {
                                    if(segment.intersects(intersections[i].intersector.ring->segments[t], &intersection))
                                    {
                                        segment.end = intersection;
                                        tindex = t;
                                        break;
                                    }
                                }

                                ring.segments.push_back(segment);

                                if(tindex >= 0)
                                {
                                    for(unsigned o = 0, t = tindex; !done && o < intersections[i].intersector.ring->segments.size(); ++o)
                                    {
                                        segment = reshp::segment((o ? intersections[i].intersector.ring->segments[t].start : intersection), intersections[i].intersector.ring->segments[t].end);

                                        if(t == static_cast<unsigned>(intersections[i].intersector.segment_index))
                                        {
                                            segment.end = intersections[i].point;
                                            done = true;
                                        }

                                        ring.segments.push_back(segment);

                                        t = (t < intersections[i].intersector.ring->segments.size() - 1 ? t + 1 : 0);
                                    }
                                }

                                s = (s ? s - 1 : intersections[i].ring->segments.size() - 1);
                            }

                            rings.push_back(ring);
                        }
                    }

                    basepolys[bpoly].rings = rings;
                    basepolys[bpoly].calculate_aabb();
                }
            } // maskpolys
        } // basepolys

        if(outputfile)
        {
            reshp::shp output;

            for(unsigned p = 0; p < basepolys.size(); ++p)
            {
                reshp::shp::record record;

                if((record.polygon = new (std::nothrow) reshp::shp::polygon()))
                {
                    record.shape = record.polygon; // Automatically deallocates record.polygon on output dtor
                    record.type = reshp::shp::shape::polygon;

                    basepolys[p].calculate_aabb();
                    basepolys[p] >> *record.polygon;
                    basepolys[p].aabb >> output.header.box;
                    output.header.type = reshp::shp::shape::polygon;

                    output.records.push_back(record);
                }
            }

            if(output.save(outputfile, verbose_))
            {
                reshp::shx indexfile;

                if(indexfile.load(output, verbose_))
                {
                    std::string indexfilename(outputfile);

                    if(indexfilename.substr(indexfilename.length() - 4) == ".shp")
                        indexfilename.replace(indexfilename.length() - 4, 4, ".shx");
                    else indexfilename += ".shx";

                    indexfile.save(indexfilename, verbose_);
                }
            }
        }
    } // handler::subtract()
} // namespace reshp
<commit_msg>Fixed verbosity on warning output in subtract function<commit_after>/* * * * * * * * * * * * *\
|*             ╔═╗ v0.3  *|
|* ╔═╦═╦═══╦═══╣ ╚═╦═╦═╗ *|
|* ║ ╔═╣ '╔╬═╗╚╣ ║ ║  '║ *|
|* ╚═╝ ╚═══╩═══╩═╩═╣ ╔═╝ *|
|* * * * * * * * * ╚═╝ * *|
|* Manipulation tool for *|
|*    ESRI Shapefiles    *|
|* * * * * * * * * * * * *|
|* http://www.npolar.no/ *|
\* * * * * * * * * * * * */

#include "../handler.hpp"
#include "../polygon.hpp"
#include "../shx.hpp"

#include <vector>
#include <cstdio>

namespace reshp
{
    void handler::subtract(const std::string& basefile, const std::string& maskfile, const char* outputfile)
    {
        if(verbose_)
            printf("subtract '%s' from '%s'\n", maskfile.c_str(), basefile.c_str());

        reshp::shp base, mask;

        if(verbose_)
            printf("  loading base shapefile '%s'\n", basefile.c_str());

        if(!base.load(basefile))
            return;

        if(verbose_)
            printf("  loading mask shapefile '%s'\n", maskfile.c_str());

        if(!mask.load(maskfile))
            return;

        std::vector<reshp::polygon> basepolys, maskpolys;

        if(verbose_)
            printf("  converting base shapefile polygons\n");

        for(unsigned r = 0; r < base.records.size(); ++r)
        {
            reshp::shp::record& record = base.records[r];

            if(record.type != reshp::shp::shape::polygon)
            {
                printf("    shapefile record type not supported as base shape for subtraction: %s\n", reshp::shp::typestr(record.type));
                continue;
            }

            if(!record.polygon)
            {
                printf("    missing polygon data in base shapefile: %s (record #%i)\n", basefile.c_str(), record.number);
                continue;
            }

            reshp::polygon poly(*record.polygon);
            basepolys.push_back(poly);
        }

        if(verbose_)
            printf("  converting mask shapefile polygons\n");

        for(unsigned r = 0; r < mask.records.size(); ++r)
        {
            reshp::shp::record& record = mask.records[r];

            if(record.type != reshp::shp::shape::polygon)
            {
                printf("    shapefile record type not supported as mask shape for subtraction: %s\n", reshp::shp::typestr(record.type));
                continue;
            }

            if(!record.polygon)
            {
                printf("    missing polygon data in mask shapefile: %s (record #%i)\n", maskfile.c_str(), record.number);
                continue;
            }

            reshp::polygon poly(*record.polygon);
            maskpolys.push_back(poly);
        }

        if(verbose_)
            printf("  testing collision in %lu polygons\n", basepolys.size() * maskpolys.size());

        for(unsigned bpoly = 0; bpoly < basepolys.size(); ++bpoly)
        {
            for(unsigned mpoly = 0; mpoly < maskpolys.size(); ++mpoly)
            {
                // Mask polygon is entirely inside base polygon
                if(maskpolys[mpoly].inside(basepolys[bpoly]))
                {
                    if(verbose_)
                        printf("    mask polygon #%u is entirely inside base polygon #%u\n", mpoly, bpoly);

                    for(unsigned r = 0; r < maskpolys[mpoly].rings.size(); ++ r)
                    {
                        if(maskpolys[mpoly].rings[r].type == reshp::polygon::ring::outer)
                        {
                            if(verbose_)
                                printf("      outer ring #%u added to base polygon as inner ring\n", r);

                            basepolys[bpoly].rings.push_back(maskpolys[mpoly].rings[r]);
                            basepolys[bpoly].rings.back().type = reshp::polygon::ring::inner;
                        }
                        else if(verbose_)
                            printf("      ignored inner ring #%u in mask polygon\n", r);
                    }

                    continue;
                }

                std::vector<reshp::polygon::intersection> intersections;
                std::vector<reshp::polygon::ring> rings;

                // Mask polygon intersects base polygon
                if(maskpolys[mpoly].intersects(basepolys[bpoly], &intersections))
                {
                    if(verbose_)
                        printf("    %lu intersections found between base polygon #%u and mask polygon #%u:\n", intersections.size(), bpoly, mpoly);

                    for(unsigned i = 0; i < intersections.size(); ++i)
                    {
                        if(verbose_)
                            printf("      [%8.4f, %8.4f]\n", intersections[i].point.x, intersections[i].point.y);

                        if(basepolys[bpoly].contains(intersections[i].segment->start))
                        {
                            bool done = false;
                            reshp::polygon::ring ring; // outer by default

                            for(unsigned n = 0, s = intersections[i].segment_index; !done && n < intersections[i].ring->segments.size(); ++n)
                            {
                                int tindex = -1;
                                reshp::point intersection;
                                reshp::segment segment((n ? intersections[i].ring->segments[s].end : intersections[i].point), intersections[i].ring->segments[s].start);

                                for(unsigned t = 0; n && t < intersections[i].intersector.ring->segments.size(); ++t)
                                {
                                    if(segment.intersects(intersections[i].intersector.ring->segments[t], &intersection))
                                    {
                                        segment.end = intersection;
                                        tindex = t;
                                        break;
                                    }
                                }

                                ring.segments.push_back(segment);

                                if(tindex >= 0)
                                {
                                    for(unsigned o = 0, t = tindex; !done && o < intersections[i].intersector.ring->segments.size(); ++o)
                                    {
                                        segment = reshp::segment((o ? intersections[i].intersector.ring->segments[t].start : intersection), intersections[i].intersector.ring->segments[t].end);

                                        if(t == static_cast<unsigned>(intersections[i].intersector.segment_index))
                                        {
                                            segment.end = intersections[i].point;
                                            done = true;
                                        }

                                        ring.segments.push_back(segment);

                                        t = (t < intersections[i].intersector.ring->segments.size() - 1 ? t + 1 : 0);
                                    }
                                }

                                s = (s ? s - 1 : intersections[i].ring->segments.size() - 1);
                            }

                            rings.push_back(ring);
                        }
                    }

                    basepolys[bpoly].rings = rings;
                    basepolys[bpoly].calculate_aabb();
                }
            } // maskpolys
        } // basepolys

        if(outputfile)
        {
            reshp::shp output;

            for(unsigned p = 0; p < basepolys.size(); ++p)
            {
                reshp::shp::record record;

                if((record.polygon = new (std::nothrow) reshp::shp::polygon()))
                {
                    record.shape = record.polygon; // Automatically deallocates record.polygon on output dtor
                    record.type = reshp::shp::shape::polygon;

                    basepolys[p].calculate_aabb();
                    basepolys[p] >> *record.polygon;
                    basepolys[p].aabb >> output.header.box;
                    output.header.type = reshp::shp::shape::polygon;

                    output.records.push_back(record);
                }
            }

            if(output.save(outputfile, verbose_))
            {
                reshp::shx indexfile;

                if(indexfile.load(output, verbose_))
                {
                    std::string indexfilename(outputfile);

                    if(indexfilename.substr(indexfilename.length() - 4) == ".shp")
                        indexfilename.replace(indexfilename.length() - 4, 4, ".shx");
                    else indexfilename += ".shx";

                    indexfile.save(indexfilename, verbose_);
                }
            }
        }
    } // handler::subtract()
} // namespace reshp
<|endoftext|>


<commit_before>//===-- IndirectCallPromotionAnalysis.cpp - Find promotion candidates ===//
//
//                      The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Helper methods for identifying profitable indirect call promotion
// candidates for an instruction when the indirect-call value profile metadata
// is available.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/IndirectCallSiteVisitor.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Debug.h"
#include <string>
#include <utility>
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "pgo-icall-prom-analysis"

// The minimum call count for the direct-call target to be considered as the
// promotion candidate.
static cl::opt<unsigned>
    ICPCountThreshold("icp-count-threshold", cl::Hidden, cl::ZeroOrMore,
                      cl::init(1000),
                      cl::desc("The minimum count to the direct call target "
                               "for the promotion"));

// The percent threshold for the direct-call target (this call site vs the
// total call count) for it to be considered as the promotion target.
static cl::opt<unsigned>
    ICPPercentThreshold("icp-percent-threshold", cl::init(33), cl::Hidden,
                        cl::ZeroOrMore,
                        cl::desc("The percentage threshold for the promotion"));

// Set the maximum number of targets to promote for a single indirect-call
// callsite.
static cl::opt<unsigned>
    MaxNumPromotions("icp-max-prom", cl::init(2), cl::Hidden, cl::ZeroOrMore,
                     cl::desc("Max number of promotions for a single indirect "
                              "call callsite"));

ICallPromotionAnalysis::ICallPromotionAnalysis() {
  ValueDataArray = llvm::make_unique<InstrProfValueData[]>(MaxNumPromotions);
}

bool ICallPromotionAnalysis::isPromotionProfitable(uint64_t Count,
                                                   uint64_t TotalCount) {
  if (Count < ICPCountThreshold)
    return false;

  unsigned Percentage = (Count * 100) / TotalCount;
  return (Percentage >= ICPPercentThreshold);
}

// Indirect-call promotion heuristic. The direct targets are sorted based on
// the count. Stop at the first target that is not promoted. Returns the
// number of candidates deemed profitable.
uint32_t ICallPromotionAnalysis::getProfitablePromotionCandidates(
    const Instruction *Inst, uint32_t NumVals, uint64_t TotalCount) {
  ArrayRef<InstrProfValueData> ValueDataRef(ValueDataArray.get(), NumVals);

  DEBUG(dbgs() << " \nWork on callsite " << *Inst << " Num_targets: " << NumVals
               << "\n");

  uint32_t I = 0;
  for (; I < MaxNumPromotions && I < NumVals; I++) {
    uint64_t Count = ValueDataRef[I].Count;
    assert(Count <= TotalCount);
    uint64_t Target = ValueDataRef[I].Value;
    DEBUG(dbgs() << " Candidate " << I << " Count=" << Count
                 << "  Target_func: " << Target << "\n");

    if (!isPromotionProfitable(Count, TotalCount)) {
      DEBUG(dbgs() << " Not promote: Cold target.\n");
      return I;
    }
    TotalCount -= Count;
  }
  return I;
}

ArrayRef<InstrProfValueData>
ICallPromotionAnalysis::getPromotionCandidatesForInstruction(
    const Instruction *I, uint32_t &NumVals, uint64_t &TotalCount,
    uint32_t &NumCandidates) {
  bool Res =
      getValueProfDataFromInst(*I, IPVK_IndirectCallTarget, MaxNumPromotions,
                               ValueDataArray.get(), NumVals, TotalCount);
  if (!Res) {
    NumCandidates = 0;
    return ArrayRef<InstrProfValueData>();
  }
  NumCandidates = getProfitablePromotionCandidates(I, NumVals, TotalCount);
  return ArrayRef<InstrProfValueData>(ValueDataArray.get(), NumVals);
}
<commit_msg>Remove another unused variable from r275216<commit_after>//===-- IndirectCallPromotionAnalysis.cpp - Find promotion candidates ===//
//
//                      The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Helper methods for identifying profitable indirect call promotion
// candidates for an instruction when the indirect-call value profile metadata
// is available.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/IndirectCallSiteVisitor.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Debug.h"
#include <string>
#include <utility>
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "pgo-icall-prom-analysis"

// The minimum call count for the direct-call target to be considered as the
// promotion candidate.
static cl::opt<unsigned>
    ICPCountThreshold("icp-count-threshold", cl::Hidden, cl::ZeroOrMore,
                      cl::init(1000),
                      cl::desc("The minimum count to the direct call target "
                               "for the promotion"));

// The percent threshold for the direct-call target (this call site vs the
// total call count) for it to be considered as the promotion target.
static cl::opt<unsigned>
    ICPPercentThreshold("icp-percent-threshold", cl::init(33), cl::Hidden,
                        cl::ZeroOrMore,
                        cl::desc("The percentage threshold for the promotion"));

// Set the maximum number of targets to promote for a single indirect-call
// callsite.
static cl::opt<unsigned>
    MaxNumPromotions("icp-max-prom", cl::init(2), cl::Hidden, cl::ZeroOrMore,
                     cl::desc("Max number of promotions for a single indirect "
                              "call callsite"));

ICallPromotionAnalysis::ICallPromotionAnalysis() {
  ValueDataArray = llvm::make_unique<InstrProfValueData[]>(MaxNumPromotions);
}

bool ICallPromotionAnalysis::isPromotionProfitable(uint64_t Count,
                                                   uint64_t TotalCount) {
  if (Count < ICPCountThreshold)
    return false;

  unsigned Percentage = (Count * 100) / TotalCount;
  return (Percentage >= ICPPercentThreshold);
}

// Indirect-call promotion heuristic. The direct targets are sorted based on
// the count. Stop at the first target that is not promoted. Returns the
// number of candidates deemed profitable.
uint32_t ICallPromotionAnalysis::getProfitablePromotionCandidates(
    const Instruction *Inst, uint32_t NumVals, uint64_t TotalCount) {
  ArrayRef<InstrProfValueData> ValueDataRef(ValueDataArray.get(), NumVals);

  DEBUG(dbgs() << " \nWork on callsite " << *Inst << " Num_targets: " << NumVals
               << "\n");

  uint32_t I = 0;
  for (; I < MaxNumPromotions && I < NumVals; I++) {
    uint64_t Count = ValueDataRef[I].Count;
    assert(Count <= TotalCount);
    DEBUG(dbgs() << " Candidate " << I << " Count=" << Count
                 << "  Target_func: " << ValueDataRef[I].Value << "\n");

    if (!isPromotionProfitable(Count, TotalCount)) {
      DEBUG(dbgs() << " Not promote: Cold target.\n");
      return I;
    }
    TotalCount -= Count;
  }
  return I;
}

ArrayRef<InstrProfValueData>
ICallPromotionAnalysis::getPromotionCandidatesForInstruction(
    const Instruction *I, uint32_t &NumVals, uint64_t &TotalCount,
    uint32_t &NumCandidates) {
  bool Res =
      getValueProfDataFromInst(*I, IPVK_IndirectCallTarget, MaxNumPromotions,
                               ValueDataArray.get(), NumVals, TotalCount);
  if (!Res) {
    NumCandidates = 0;
    return ArrayRef<InstrProfValueData>();
  }
  NumCandidates = getProfitablePromotionCandidates(I, NumVals, TotalCount);
  return ArrayRef<InstrProfValueData>(ValueDataArray.get(), NumVals);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: AccessibleOutlineView.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: thb $ $Date: 2002-06-13 18:51:34 $
 *
 *  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 _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_
#include <com/sun/star/drawing/XDrawPage.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XDRAWVIEW_HPP_
#include <com/sun/star/drawing/XDrawView.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XSHAPES_HPP_
#include <com/sun/star/drawing/XShapes.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTINFOSUPPLIER_HPP_
#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTBROADCASTER_HPP_
#include <com/sun/star/document/XEventBroadcaster.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBLE_ACCESSIBLEEVENTID_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleEventId.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_INDEXOUTOFBOUNDSEXCEPTION_HPP_
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULSTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _RTL_USTRING_H_
#include <rtl/ustring.h>
#endif
#ifndef _SFXFRAME_HXX
#include<sfx2/viewfrm.hxx>
#endif

#include <svx/AccessibleShape.hxx>

#include <svx/svdobj.hxx>
#include <svx/svdmodel.hxx>
#include <svx/unoapi.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include "sdwindow.hxx"
#include <vcl/svapp.hxx>

#ifndef _SD_SDWINDOW_HXX
#include "sdwindow.hxx"
#endif
#ifndef _SD_VIEWSHEL_HXX
#include "viewshel.hxx"
#endif
#ifndef _SD_OUTLNVSH_HXX
#include "outlnvsh.hxx"
#endif
#ifndef _SD_SDVIEW_HXX
#include "sdview.hxx"
#endif
#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_OUTLINE_VIEW_HXX
#include "AccessibleOutlineView.hxx"
#endif
#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_OUTLINE_EDITSOURCE_HXX
#include "AccessibleOutlineEditSource.hxx"
#endif

#include <memory>

using namespace ::com::sun::star;
using namespace ::drafts::com::sun::star::accessibility;

namespace accessibility {

//=====  internal  ============================================================

AccessibleOutlineView::AccessibleOutlineView (
    SdWindow* pSdWindow,
    SdOutlineViewShell* pViewShell,
    const uno::Reference<frame::XController>& rxController,
    const uno::Reference<XAccessible>& rxParent)
    : AccessibleDocumentViewBase (pSdWindow, pViewShell, rxController, rxParent),
      maTextHelper( this,
                    ::std::auto_ptr< SvxEditSource >( NULL ) )
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // Beware! Here we leave the paths of the UNO API and descend into the
    // depths of the core.  Necessary for makeing the edit engine accessible.
    if( pViewShell && pSdWindow )
    {
        SdView* pView = pViewShell->GetView();

        if( pView && pView->ISA(SdOutlineView) )
        {
            OutlinerView* pOutlineView = static_cast< SdOutlineView* >(pView)->GetViewByWindow( pSdWindow );
            SdrOutliner* pOutliner = static_cast< SdOutlineView* >(pView)->GetOutliner();

            if( pOutlineView && pOutliner )
            {
                maTextHelper.SetEditSource( ::std::auto_ptr< SvxEditSource >( new AccessibleOutlineEditSource(
                                                                                *pOutliner, *pView, *pOutlineView, *pSdWindow ) ) );
            }
        }
    }
}

AccessibleOutlineView::~AccessibleOutlineView (void)
{
    OSL_TRACE ("~AccessibleOutlineView");
}

void AccessibleOutlineView::Init (void)
{
    AccessibleDocumentViewBase::Init ();
}

void AccessibleOutlineView::ViewForwarderChanged (ChangeType aChangeType,
    const IAccessibleViewForwarder* pViewForwarder)
{
    AccessibleDocumentViewBase::ViewForwarderChanged (aChangeType, pViewForwarder);

    UpdateChildren();
}

//=====  XAccessibleContext  ==================================================

sal_Int32 SAL_CALL
    AccessibleOutlineView::getAccessibleChildCount (void)
    throw (uno::RuntimeException)
{
    // forward
    return maTextHelper.GetChildCount();

    return 0;
}

uno::Reference<XAccessible> SAL_CALL
    AccessibleOutlineView::getAccessibleChild (long nIndex)
    throw (::com::sun::star::uno::RuntimeException)
{
    // Forward request to children manager.
    return maTextHelper.GetChild(nIndex);
}

//=====  XAccessibleEventBroadcaster  ========================================

void SAL_CALL AccessibleOutlineView::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException)
{
    // delegate listener handling to children manager.
    maTextHelper.AddEventListener(xListener);
}

void SAL_CALL AccessibleOutlineView::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException)
{
    // forward
    maTextHelper.RemoveEventListener(xListener);
}

//=====  XServiceInfo  ========================================================

::rtl::OUString SAL_CALL
    AccessibleOutlineView::getImplementationName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleOutlineView"));
}

//=====  XEventListener  ======================================================

void SAL_CALL
    AccessibleOutlineView::disposing (const lang::EventObject& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    // dispose children
    maTextHelper.SetEditSource( ::std::auto_ptr< SvxEditSource >(NULL) );

    AccessibleDocumentViewBase::disposing (rEventObject);
}

//=====  protected internal  ==================================================

void AccessibleOutlineView::FireEvent(const AccessibleEventObject& aEvent )
{
    // delegate listener handling to children manager.
    maTextHelper.FireEvent(aEvent);
}

void AccessibleOutlineView::Activated (void)
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // delegate listener handling to children manager.
    maTextHelper.SetFocus(sal_True);
}

void AccessibleOutlineView::Deactivated (void)
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // delegate listener handling to children manager.
    maTextHelper.SetFocus(sal_False);
}

void SAL_CALL AccessibleOutlineView::disposing (void)
{
    // dispose children
    maTextHelper.SetEditSource( ::std::auto_ptr< SvxEditSource >(NULL) );

    AccessibleDocumentViewBase::disposing ();
}

//=====  XPropertyChangeListener  =============================================

void SAL_CALL
    AccessibleOutlineView::propertyChange (const beans::PropertyChangeEvent& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    AccessibleDocumentViewBase::propertyChange (rEventObject);

    OSL_TRACE ("AccessibleOutlineView::propertyChange");
    if (rEventObject.PropertyName == ::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("CurrentPage")))
    {
        OSL_TRACE ("    current page changed");

        // The current page changed. Update the children accordingly.
        UpdateChildren();
    }
    else if (rEventObject.PropertyName == ::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("VisibleArea")))
    {
        OSL_TRACE ("    visible area changed");

        // The visible area changed. Update the children accordingly.
        UpdateChildren();
    }
    else
    {
        OSL_TRACE ("  unhandled");
    }
    OSL_TRACE ("  done");
}

/// Create a name for this view.
::rtl::OUString
    AccessibleOutlineView::CreateAccessibleName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString (
        RTL_CONSTASCII_USTRINGPARAM("AccessibleOutlineView"));
}

/** Create a description for this view.  Use the model's description or URL
    if a description is not available.
*/
::rtl::OUString
    AccessibleOutlineView::CreateAccessibleDescription (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    rtl::OUString sDescription;

    sDescription = ::rtl::OUString (
        RTL_CONSTASCII_USTRINGPARAM("Accessible Draw Document Outline"));

    return sDescription;
}

void AccessibleOutlineView::UpdateChildren()
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // Update visible children
    maTextHelper.UpdateChildren();
}

} // end of namespace accessibility
<commit_msg>#100593# Adaptions to new AccessibleTextHelper/AccessibleStaticTextBase interface<commit_after>/*************************************************************************
 *
 *  $RCSfile: AccessibleOutlineView.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: thb $ $Date: 2002-06-26 11:18:14 $
 *
 *  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 _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_
#include <com/sun/star/drawing/XDrawPage.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XDRAWVIEW_HPP_
#include <com/sun/star/drawing/XDrawView.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XSHAPES_HPP_
#include <com/sun/star/drawing/XShapes.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTINFOSUPPLIER_HPP_
#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTBROADCASTER_HPP_
#include <com/sun/star/document/XEventBroadcaster.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBLE_ACCESSIBLEEVENTID_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleEventId.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_INDEXOUTOFBOUNDSEXCEPTION_HPP_
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULSTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _RTL_USTRING_H_
#include <rtl/ustring.h>
#endif
#ifndef _SFXFRAME_HXX
#include<sfx2/viewfrm.hxx>
#endif

#include <svx/AccessibleShape.hxx>

#include <svx/svdobj.hxx>
#include <svx/svdmodel.hxx>
#include <svx/unoapi.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include "sdwindow.hxx"
#include <vcl/svapp.hxx>

#ifndef _SD_SDWINDOW_HXX
#include "sdwindow.hxx"
#endif
#ifndef _SD_VIEWSHEL_HXX
#include "viewshel.hxx"
#endif
#ifndef _SD_OUTLNVSH_HXX
#include "outlnvsh.hxx"
#endif
#ifndef _SD_SDVIEW_HXX
#include "sdview.hxx"
#endif
#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_OUTLINE_VIEW_HXX
#include "AccessibleOutlineView.hxx"
#endif
#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_OUTLINE_EDITSOURCE_HXX
#include "AccessibleOutlineEditSource.hxx"
#endif

#include <memory>

using namespace ::com::sun::star;
using namespace ::drafts::com::sun::star::accessibility;

namespace accessibility {

//=====  internal  ============================================================

AccessibleOutlineView::AccessibleOutlineView (
    SdWindow* pSdWindow,
    SdOutlineViewShell* pViewShell,
    const uno::Reference<frame::XController>& rxController,
    const uno::Reference<XAccessible>& rxParent)
    : AccessibleDocumentViewBase (pSdWindow, pViewShell, rxController, rxParent),
      maTextHelper( ::std::auto_ptr< SvxEditSource >( NULL ) )
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // Beware! Here we leave the paths of the UNO API and descend into the
    // depths of the core.  Necessary for makeing the edit engine accessible.
    if( pViewShell && pSdWindow )
    {
        SdView* pView = pViewShell->GetView();

        if( pView && pView->ISA(SdOutlineView) )
        {
            OutlinerView* pOutlineView = static_cast< SdOutlineView* >(pView)->GetViewByWindow( pSdWindow );
            SdrOutliner* pOutliner = static_cast< SdOutlineView* >(pView)->GetOutliner();

            if( pOutlineView && pOutliner )
            {
                maTextHelper.SetEditSource( ::std::auto_ptr< SvxEditSource >( new AccessibleOutlineEditSource(
                                                                                *pOutliner, *pView, *pOutlineView, *pSdWindow ) ) );
            }
        }
    }
}

AccessibleOutlineView::~AccessibleOutlineView (void)
{
    OSL_TRACE ("~AccessibleOutlineView");
}

void AccessibleOutlineView::Init (void)
{
    AccessibleDocumentViewBase::Init ();

    maTextHelper.SetEventSource(this);
}

void AccessibleOutlineView::ViewForwarderChanged (ChangeType aChangeType,
    const IAccessibleViewForwarder* pViewForwarder)
{
    AccessibleDocumentViewBase::ViewForwarderChanged (aChangeType, pViewForwarder);

    UpdateChildren();
}

//=====  XAccessibleContext  ==================================================

sal_Int32 SAL_CALL
    AccessibleOutlineView::getAccessibleChildCount (void)
    throw (uno::RuntimeException)
{
    // forward
    return maTextHelper.GetChildCount();

    return 0;
}

uno::Reference<XAccessible> SAL_CALL
    AccessibleOutlineView::getAccessibleChild (long nIndex)
    throw (::com::sun::star::uno::RuntimeException)
{
    // Forward request to children manager.
    return maTextHelper.GetChild(nIndex);
}

//=====  XAccessibleEventBroadcaster  ========================================

void SAL_CALL AccessibleOutlineView::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException)
{
    // delegate listener handling to children manager.
    maTextHelper.AddEventListener(xListener);
}

void SAL_CALL AccessibleOutlineView::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException)
{
    // forward
    maTextHelper.RemoveEventListener(xListener);
}

//=====  XServiceInfo  ========================================================

::rtl::OUString SAL_CALL
    AccessibleOutlineView::getImplementationName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleOutlineView"));
}

//=====  XEventListener  ======================================================

void SAL_CALL
    AccessibleOutlineView::disposing (const lang::EventObject& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    // dispose children
    maTextHelper.Dispose();

    AccessibleDocumentViewBase::disposing (rEventObject);
}

//=====  protected internal  ==================================================

void AccessibleOutlineView::FireEvent(const AccessibleEventObject& aEvent )
{
    // delegate listener handling to children manager.
    maTextHelper.FireEvent(aEvent);
}

void AccessibleOutlineView::Activated (void)
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // delegate listener handling to children manager.
    maTextHelper.SetFocus(sal_True);
}

void AccessibleOutlineView::Deactivated (void)
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // delegate listener handling to children manager.
    maTextHelper.SetFocus(sal_False);
}

void SAL_CALL AccessibleOutlineView::disposing (void)
{
    // dispose children
    maTextHelper.Dispose();

    AccessibleDocumentViewBase::disposing ();
}

//=====  XPropertyChangeListener  =============================================

void SAL_CALL
    AccessibleOutlineView::propertyChange (const beans::PropertyChangeEvent& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    AccessibleDocumentViewBase::propertyChange (rEventObject);

    OSL_TRACE ("AccessibleOutlineView::propertyChange");
    if (rEventObject.PropertyName == ::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("CurrentPage")))
    {
        OSL_TRACE ("    current page changed");

        // The current page changed. Update the children accordingly.
        UpdateChildren();
    }
    else if (rEventObject.PropertyName == ::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("VisibleArea")))
    {
        OSL_TRACE ("    visible area changed");

        // The visible area changed. Update the children accordingly.
        UpdateChildren();
    }
    else
    {
        OSL_TRACE ("  unhandled");
    }
    OSL_TRACE ("  done");
}

/// Create a name for this view.
::rtl::OUString
    AccessibleOutlineView::CreateAccessibleName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString (
        RTL_CONSTASCII_USTRINGPARAM("AccessibleOutlineView"));
}

/** Create a description for this view.  Use the model's description or URL
    if a description is not available.
*/
::rtl::OUString
    AccessibleOutlineView::CreateAccessibleDescription (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    rtl::OUString sDescription;

    sDescription = ::rtl::OUString (
        RTL_CONSTASCII_USTRINGPARAM("Accessible Draw Document Outline"));

    return sDescription;
}

void AccessibleOutlineView::UpdateChildren()
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // Update visible children
    maTextHelper.UpdateChildren();
}

} // end of namespace accessibility
<|endoftext|>


<commit_before>//===-- WebAssemblyPeephole.cpp - WebAssembly Peephole Optimiztions -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Late peephole optimizations for WebAssembly.
///
//===----------------------------------------------------------------------===//

#include "WebAssembly.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssemblyMachineFunctionInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
using namespace llvm;

#define DEBUG_TYPE "wasm-peephole"

namespace {
class WebAssemblyPeephole final : public MachineFunctionPass {
  const char *getPassName() const override {
    return "WebAssembly late peephole optimizer";
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    MachineFunctionPass::getAnalysisUsage(AU);
  }

  bool runOnMachineFunction(MachineFunction &MF) override;

public:
  static char ID;
  WebAssemblyPeephole() : MachineFunctionPass(ID) {}
};
} // end anonymous namespace

char WebAssemblyPeephole::ID = 0;
FunctionPass *llvm::createWebAssemblyPeephole() {
  return new WebAssemblyPeephole();
}

bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
  bool Changed = false;

  MachineRegisterInfo &MRI = MF.getRegInfo();
  WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();

  for (auto &MBB : MF)
    for (auto &MI : MBB)
      switch (MI.getOpcode()) {
      default:
        break;
      case WebAssembly::STORE8_I32:
      case WebAssembly::STORE16_I32:
      case WebAssembly::STORE8_I64:
      case WebAssembly::STORE16_I64:
      case WebAssembly::STORE32_I64:
      case WebAssembly::STORE_F32:
      case WebAssembly::STORE_F64:
      case WebAssembly::STORE_I32:
      case WebAssembly::STORE_I64: {
        // Store instructions return their value operand. If we ended up using
        // the same register for both, replace it with a dead def so that it
        // can use $discard instead.
        MachineOperand &MO = MI.getOperand(0);
        unsigned OldReg = MO.getReg();
        if (OldReg == MI.getOperand(3).getReg()) {
          unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg));
          MO.setReg(NewReg);
          MO.setIsDead();
          MFI.stackifyVReg(NewReg);
          MFI.addWAReg(NewReg, WebAssemblyFunctionInfo::UnusedReg);
        }
      }
      }

  return Changed;
}
<commit_msg>[WebAssembly] Fix WebAssemblyPeephole to set Changed to true when making changes.<commit_after>//===-- WebAssemblyPeephole.cpp - WebAssembly Peephole Optimiztions -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Late peephole optimizations for WebAssembly.
///
//===----------------------------------------------------------------------===//

#include "WebAssembly.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssemblyMachineFunctionInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
using namespace llvm;

#define DEBUG_TYPE "wasm-peephole"

namespace {
class WebAssemblyPeephole final : public MachineFunctionPass {
  const char *getPassName() const override {
    return "WebAssembly late peephole optimizer";
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    MachineFunctionPass::getAnalysisUsage(AU);
  }

  bool runOnMachineFunction(MachineFunction &MF) override;

public:
  static char ID;
  WebAssemblyPeephole() : MachineFunctionPass(ID) {}
};
} // end anonymous namespace

char WebAssemblyPeephole::ID = 0;
FunctionPass *llvm::createWebAssemblyPeephole() {
  return new WebAssemblyPeephole();
}

bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
  bool Changed = false;

  MachineRegisterInfo &MRI = MF.getRegInfo();
  WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();

  for (auto &MBB : MF)
    for (auto &MI : MBB)
      switch (MI.getOpcode()) {
      default:
        break;
      case WebAssembly::STORE8_I32:
      case WebAssembly::STORE16_I32:
      case WebAssembly::STORE8_I64:
      case WebAssembly::STORE16_I64:
      case WebAssembly::STORE32_I64:
      case WebAssembly::STORE_F32:
      case WebAssembly::STORE_F64:
      case WebAssembly::STORE_I32:
      case WebAssembly::STORE_I64: {
        // Store instructions return their value operand. If we ended up using
        // the same register for both, replace it with a dead def so that it
        // can use $discard instead.
        MachineOperand &MO = MI.getOperand(0);
        unsigned OldReg = MO.getReg();
        if (OldReg == MI.getOperand(3).getReg()) {
          Changed = true;
          unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg));
          MO.setReg(NewReg);
          MO.setIsDead();
          MFI.stackifyVReg(NewReg);
          MFI.addWAReg(NewReg, WebAssemblyFunctionInfo::UnusedReg);
        }
      }
      }

  return Changed;
}
<|endoftext|>