<commit_before>/*
    This file is part of KOrganizer.

    Copyright (c) 2000 Cornelius Schumacher <schumacher@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "korganizer_part.h"

#include "calendarview.h"
#include "actionmanager.h"
#include "koglobals.h"
#include "koprefs.h"
#include "resourceview.h"
#include "aboutdata.h"
#include "kocore.h"
#include "korganizerifaceimpl.h"
#include "stdcalendar.h"

#include "kalarmd/alarmdaemoniface_stub.h"

#include <libkcal/calendarlocal.h>
#include <libkcal/calendarresources.h>
#include <libkcal/resourcecalendar.h>
#include <libkcal/resourcelocal.h>

#include <kpopupmenu.h>
#include <kinstance.h>
#include <klocale.h>
#include <kaboutdata.h>
#include <kiconloader.h>
#include <kaction.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kconfig.h>
#include <kprocess.h>
#include <ktempfile.h>
#include <kstatusbar.h>
#include <kkeydialog.h>
#include <kparts/genericfactory.h>

#include <kparts/statusbarextension.h>

#include <sidebarextension.h>
#include <infoextension.h>

#include <qapplication.h>
#include <qfile.h>
#include <qtimer.h>
#include <qlayout.h>

typedef KParts::GenericFactory< KOrganizerPart > KOrganizerFactory;
K_EXPORT_COMPONENT_FACTORY( libkorganizerpart, KOrganizerFactory )

KOrganizerPart::KOrganizerPart( QWidget *parentWidget, const char *widgetName,
                                QObject *parent, const char *name,
                                const QStringList & ) :
  KParts::ReadOnlyPart(parent, name)
{
  KOCore::self()->setXMLGUIClient( this );

  QString pname( name );

  // create a canvas to insert our widget
  QWidget *canvas = new QWidget( parentWidget, widgetName );
  canvas->setFocusPolicy( QWidget::ClickFocus );
  setWidget( canvas );
  mView = new CalendarView( canvas );

  mActionManager = new ActionManager( this, mView, this, this, true );
  (void)new KOrganizerIfaceImpl( mActionManager, this, "IfaceImpl" );

  if ( pname == "kontact" ) {
    mActionManager->createCalendarResources();
    setHasDocument( false );
    KOrg::StdCalendar::self()->load();
    mView->updateCategories();
  } else {
    mActionManager->createCalendarLocal();
    setHasDocument( true );
  }

  mBrowserExtension = new KOrganizerBrowserExtension( this );
  mStatusBarExtension = new KParts::StatusBarExtension( this );

  setInstance( KOrganizerFactory::instance() );

  QVBoxLayout *topLayout = new QVBoxLayout( canvas );
  topLayout->addWidget( mView );

  KGlobal::iconLoader()->addAppDir( "korganizer" );

  new KParts::SideBarExtension( mView->leftFrame(), this, "SBE" );

  KParts::InfoExtension *ie = new KParts::InfoExtension( this,
                                                         "KOrganizerInfo" );
  connect( mView, SIGNAL( incidenceSelected( Incidence * ) ),
           SLOT( slotChangeInfo( Incidence * ) ) );
  connect( this, SIGNAL( textChanged( const QString & ) ),
           ie, SIGNAL( textChanged( const QString & ) ) );

  mView->show();

  mActionManager->init();
  mActionManager->readSettings();
  connect( mActionManager, SIGNAL( actionKeyBindings() ),
           SLOT( configureKeyBindings() ) );

  setXMLFile( "korganizer_part.rc" );
  mActionManager->loadParts();
}

KOrganizerPart::~KOrganizerPart()
{
  mActionManager->saveCalendar();
  mActionManager->writeSettings();

  delete mActionManager;
  mActionManager = 0;

  closeURL();
}

KAboutData *KOrganizerPart::createAboutData()
{
  return KOrg::AboutData::self();
}

void KOrganizerPart::startCompleted( KProcess *process )
{
  delete process;
}

void KOrganizerPart::slotChangeInfo( Incidence *incidence )
{
  if ( incidence ) {
    emit textChanged( incidence->summary() + " / " +
                      incidence->dtStartTimeStr() );
  } else {
    emit textChanged( QString::null );
  }
}

QWidget *KOrganizerPart::topLevelWidget()
{
  return mView->topLevelWidget();
}

ActionManager *KOrganizerPart::actionManager()
{
  return mActionManager;
}

void KOrganizerPart::showStatusMessage( const QString &message )
{
  KStatusBar *statusBar = mStatusBarExtension->statusBar();
  if ( statusBar ) statusBar->message( message );
}

KOrg::CalendarViewBase *KOrganizerPart::view() const
{
  return mView;
}

bool KOrganizerPart::openURL( const KURL &url, bool merge )
{
  return mActionManager->openURL( url, merge );
}

bool KOrganizerPart::saveURL()
{
  return mActionManager->saveURL();
}

bool KOrganizerPart::saveAsURL( const KURL &kurl )
{
  return mActionManager->saveAsURL( kurl );
}

KURL KOrganizerPart::getCurrentURL() const
{
  return mActionManager->url();
}

bool KOrganizerPart::openFile()
{
  mView->openCalendar( m_file );
  mView->show();
  return true;
}

void KOrganizerPart::configureKeyBindings()
{
  KKeyDialog::configure( actionCollection(), true );
}

KOrganizerBrowserExtension::KOrganizerBrowserExtension(KOrganizerPart *parent) :
  KParts::BrowserExtension(parent, "KOrganizerBrowserExtension")
{
}

KOrganizerBrowserExtension::~KOrganizerBrowserExtension()
{
}

using namespace KParts;

#include "korganizer_part.moc"
<commit_msg>When run as kontact part, korganizer didn't start the alarm daemon so far. In the standalone case this was done in KOrganizerApp, but for a Part we have to do it in the constructor of KOrganizerPart.<commit_after>/*
    This file is part of KOrganizer.

    Copyright (c) 2000 Cornelius Schumacher <schumacher@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "korganizer_part.h"

#include "calendarview.h"
#include "actionmanager.h"
#include "koglobals.h"
#include "koprefs.h"
#include "resourceview.h"
#include "aboutdata.h"
#include "kocore.h"
#include "korganizerifaceimpl.h"
#include "stdcalendar.h"

#include "kalarmd/alarmdaemoniface_stub.h"

#include <libkcal/calendarlocal.h>
#include <libkcal/calendarresources.h>
#include <libkcal/resourcecalendar.h>
#include <libkcal/resourcelocal.h>

#include <kpopupmenu.h>
#include <kinstance.h>
#include <klocale.h>
#include <kaboutdata.h>
#include <kiconloader.h>
#include <kaction.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kconfig.h>
#include <kprocess.h>
#include <ktempfile.h>
#include <kstatusbar.h>
#include <kkeydialog.h>
#include <kparts/genericfactory.h>

#include <kparts/statusbarextension.h>

#include <sidebarextension.h>
#include <infoextension.h>

#include <qapplication.h>
#include <qfile.h>
#include <qtimer.h>
#include <qlayout.h>

typedef KParts::GenericFactory< KOrganizerPart > KOrganizerFactory;
K_EXPORT_COMPONENT_FACTORY( libkorganizerpart, KOrganizerFactory )

KOrganizerPart::KOrganizerPart( QWidget *parentWidget, const char *widgetName,
                                QObject *parent, const char *name,
                                const QStringList & ) :
  KParts::ReadOnlyPart(parent, name)
{
  KOCore::self()->setXMLGUIClient( this );

  QString pname( name );

  // create a canvas to insert our widget
  QWidget *canvas = new QWidget( parentWidget, widgetName );
  canvas->setFocusPolicy( QWidget::ClickFocus );
  setWidget( canvas );
  mView = new CalendarView( canvas );

  mActionManager = new ActionManager( this, mView, this, this, true );
  (void)new KOrganizerIfaceImpl( mActionManager, this, "IfaceImpl" );

  if ( pname == "kontact" ) {
    mActionManager->createCalendarResources();
    setHasDocument( false );
    KOrg::StdCalendar::self()->load();
    mView->updateCategories();
  } else {
    mActionManager->createCalendarLocal();
    setHasDocument( true );
  }

  mBrowserExtension = new KOrganizerBrowserExtension( this );
  mStatusBarExtension = new KParts::StatusBarExtension( this );

  setInstance( KOrganizerFactory::instance() );

  QVBoxLayout *topLayout = new QVBoxLayout( canvas );
  topLayout->addWidget( mView );

  KGlobal::iconLoader()->addAppDir( "korganizer" );

  new KParts::SideBarExtension( mView->leftFrame(), this, "SBE" );

  KParts::InfoExtension *ie = new KParts::InfoExtension( this,
                                                         "KOrganizerInfo" );
  connect( mView, SIGNAL( incidenceSelected( Incidence * ) ),
           SLOT( slotChangeInfo( Incidence * ) ) );
  connect( this, SIGNAL( textChanged( const QString & ) ),
           ie, SIGNAL( textChanged( const QString & ) ) );

  mView->show();

  mActionManager->init();
  mActionManager->readSettings();
  connect( mActionManager, SIGNAL( actionKeyBindings() ),
           SLOT( configureKeyBindings() ) );

  setXMLFile( "korganizer_part.rc" );
  mActionManager->loadParts();
  // If korganizer is run as part inside kontact, the alarmdaemon
  // is not started by KOrganizerApp, so we have to start it here.
  KOGlobals::self()->alarmClient()->startDaemon();
}

KOrganizerPart::~KOrganizerPart()
{
  mActionManager->saveCalendar();
  mActionManager->writeSettings();

  delete mActionManager;
  mActionManager = 0;

  closeURL();
}

KAboutData *KOrganizerPart::createAboutData()
{
  return KOrg::AboutData::self();
}

void KOrganizerPart::startCompleted( KProcess *process )
{
  delete process;
}

void KOrganizerPart::slotChangeInfo( Incidence *incidence )
{
  if ( incidence ) {
    emit textChanged( incidence->summary() + " / " +
                      incidence->dtStartTimeStr() );
  } else {
    emit textChanged( QString::null );
  }
}

QWidget *KOrganizerPart::topLevelWidget()
{
  return mView->topLevelWidget();
}

ActionManager *KOrganizerPart::actionManager()
{
  return mActionManager;
}

void KOrganizerPart::showStatusMessage( const QString &message )
{
  KStatusBar *statusBar = mStatusBarExtension->statusBar();
  if ( statusBar ) statusBar->message( message );
}

KOrg::CalendarViewBase *KOrganizerPart::view() const
{
  return mView;
}

bool KOrganizerPart::openURL( const KURL &url, bool merge )
{
  return mActionManager->openURL( url, merge );
}

bool KOrganizerPart::saveURL()
{
  return mActionManager->saveURL();
}

bool KOrganizerPart::saveAsURL( const KURL &kurl )
{
  return mActionManager->saveAsURL( kurl );
}

KURL KOrganizerPart::getCurrentURL() const
{
  return mActionManager->url();
}

bool KOrganizerPart::openFile()
{
  mView->openCalendar( m_file );
  mView->show();
  return true;
}

void KOrganizerPart::configureKeyBindings()
{
  KKeyDialog::configure( actionCollection(), true );
}

KOrganizerBrowserExtension::KOrganizerBrowserExtension(KOrganizerPart *parent) :
  KParts::BrowserExtension(parent, "KOrganizerBrowserExtension")
{
}

KOrganizerBrowserExtension::~KOrganizerBrowserExtension()
{
}

using namespace KParts;

#include "korganizer_part.moc"
<|endoftext|>


<commit_before>// A work-in-progress llvm backend

#include <taichi/common/util.h>
#include <taichi/io/io.h>
#include <set>

#include "cuda_context.h"
#include "../util.h"
#include "codegen_cuda.h"
#include "../program.h"
#include "../ir.h"

#if defined(TLANG_WITH_LLVM)

#include "codegen_llvm.h"

#endif

TLANG_NAMESPACE_BEGIN

#if defined(TLANG_WITH_LLVM)

using namespace llvm;

// NVVM IR Spec:
// https://docs.nvidia.com/cuda/archive/10.0/pdf/NVVM_IR_Specification.pdf

class CodeGenLLVMGPU : public CodeGenLLVM {
 public:
  int kernel_grid_dim;
  int kernel_block_dim;

  CodeGenLLVMGPU(CodeGenBase *codegen_base, Kernel *kernel)
      : CodeGenLLVM(codegen_base, kernel) {
  }

  FunctionType compile_module_to_executable() override {
#if defined(TLANG_WITH_CUDA)
    llvm::Function *func = module->getFunction("test_kernel");

    /*******************************************************************
    Example annotation from llvm PTX doc:

    define void @kernel(float addrspace(1)* %A,
                        float addrspace(1)* %B,
                        float addrspace(1)* %C);

    !nvvm.annotations = !{!0}
    !0 = !{void (float addrspace(1)*,
                 float addrspace(1)*,
                 float addrspace(1)*)* @kernel, !"kernel", i32 1}
    *******************************************************************/

    // Mark kernel function as a CUDA __global__ function
    // Add the nvvm annotation that it is considered a kernel function.

    llvm::Metadata *md_args[] = {
        llvm::ValueAsMetadata::get(func),
        MDString::get(*llvm_context, "kernel"),
        llvm::ValueAsMetadata::get(tlctx->get_constant(1))};

    MDNode *md_node = MDNode::get(*llvm_context, md_args);

    module->getOrInsertNamedMetadata("nvvm.annotations")->addOperand(md_node);

    auto ptx = compile_module_to_ptx(module);
    auto cuda_kernel = cuda_context.compile(ptx, kernel_name);
    return [=](Context context) {
      cuda_context.launch(cuda_kernel, &context, kernel_grid_dim,
                          kernel_block_dim);
    };
#else
    TC_NOT_IMPLEMENTED;
    return nullptr;
#endif
  }

  void visit(PrintStmt *stmt) override {
    TC_ASSERT(stmt->width() == 1);

    auto value_type = tlctx->get_data_type(stmt->stmt->ret_type.data_type);

    std::string format;

    auto value = stmt->stmt->value;

    if (stmt->stmt->ret_type.data_type == DataType::i32) {
      format = "%d";
    } else if (stmt->stmt->ret_type.data_type == DataType::f32) {
      value_type = llvm::Type::getDoubleTy(*llvm_context);
      value = builder->CreateFPExt(value, value_type);
      format = "%f";
    } else if (stmt->stmt->ret_type.data_type == DataType::f64) {
      format = "%f";
    } else {
      TC_NOT_IMPLEMENTED
    }

    std::vector<llvm::Type *> types{value_type};
    auto stype = llvm::StructType::get(*llvm_context, types, false);
    auto values = builder->CreateAlloca(stype);
    auto value_ptr = builder->CreateGEP(
        values, {tlctx->get_constant(0), tlctx->get_constant(0)});
    builder->CreateStore(value, value_ptr);

    auto format_str = "[debug] " + stmt->str + " = " + format + "\n";

    stmt->value = ModuleBuilder::call(
        builder, "vprintf",
        builder->CreateGlobalStringPtr(format_str, "format_string"),
        builder->CreateBitCast(values,
                               llvm::Type::getInt8PtrTy(*llvm_context)));
  }

  void visit(RangeForStmt *for_stmt) override {
    if (offloaded) {
      create_naive_range_for(for_stmt);
    } else {
      offloaded = true;
      auto loop_begin = for_stmt->begin->as<ConstStmt>()->val[0].val_int32();
      auto loop_end = for_stmt->end->as<ConstStmt>()->val[0].val_int32();
      auto loop_block_dim = for_stmt->block_size;
      kernel_grid_dim =
          (loop_end - loop_begin + loop_block_dim - 1) / loop_block_dim;
      kernel_block_dim = loop_block_dim;
      BasicBlock *body = BasicBlock::Create(*llvm_context, "loop_body", func);
      BasicBlock *after_loop = BasicBlock::Create(*llvm_context, "block", func);

      auto threadIdx =
          builder->CreateIntrinsic(Intrinsic::nvvm_read_ptx_sreg_tid_x, {}, {});
      auto blockIdx = builder->CreateIntrinsic(
          Intrinsic::nvvm_read_ptx_sreg_ctaid_x, {}, {});
      auto blockDim = builder->CreateIntrinsic(
          Intrinsic::nvvm_read_ptx_sreg_ntid_x, {}, {});

      auto loop_id = builder->CreateAdd(
          for_stmt->begin->value,
          builder->CreateAdd(threadIdx,
                             builder->CreateMul(blockIdx, blockDim)));

      builder->CreateStore(loop_id, for_stmt->loop_var->value);

      auto cond = builder->CreateICmp(
          llvm::CmpInst::Predicate::ICMP_SLT,
          builder->CreateLoad(for_stmt->loop_var->value), for_stmt->end->value);

      builder->CreateCondBr(cond, body, after_loop);
      {
        // body cfg
        builder->SetInsertPoint(body);
        for_stmt->body->accept(this);
        builder->CreateBr(after_loop);
      }

      // create_increment(for_stmt->loop_var->value, tlctx->get_constant(1));

      builder->SetInsertPoint(after_loop);
      // builder->CreateRetVoid();

      offloaded = false;
    }
  }
};

FunctionType GPUCodeGen::codegen_llvm() {
  return CodeGenLLVMGPU(this, kernel).gen();
}

#else

FunctionType GPUCodeGen::codegen_llvm() {
  TC_ERROR("LLVM not found");
}

#endif

TLANG_NAMESPACE_END
<commit_msg>fixed cuda loop block size<commit_after>// A work-in-progress llvm backend

#include <taichi/common/util.h>
#include <taichi/io/io.h>
#include <set>

#include "cuda_context.h"
#include "../util.h"
#include "codegen_cuda.h"
#include "../program.h"
#include "../ir.h"

#if defined(TLANG_WITH_LLVM)

#include "codegen_llvm.h"

#endif

TLANG_NAMESPACE_BEGIN

#if defined(TLANG_WITH_LLVM)

using namespace llvm;

// NVVM IR Spec:
// https://docs.nvidia.com/cuda/archive/10.0/pdf/NVVM_IR_Specification.pdf

class CodeGenLLVMGPU : public CodeGenLLVM {
 public:
  int kernel_grid_dim;
  int kernel_block_dim;

  CodeGenLLVMGPU(CodeGenBase *codegen_base, Kernel *kernel)
      : CodeGenLLVM(codegen_base, kernel) {
  }

  FunctionType compile_module_to_executable() override {
#if defined(TLANG_WITH_CUDA)
    llvm::Function *func = module->getFunction("test_kernel");

    /*******************************************************************
    Example annotation from llvm PTX doc:

    define void @kernel(float addrspace(1)* %A,
                        float addrspace(1)* %B,
                        float addrspace(1)* %C);

    !nvvm.annotations = !{!0}
    !0 = !{void (float addrspace(1)*,
                 float addrspace(1)*,
                 float addrspace(1)*)* @kernel, !"kernel", i32 1}
    *******************************************************************/

    // Mark kernel function as a CUDA __global__ function
    // Add the nvvm annotation that it is considered a kernel function.

    llvm::Metadata *md_args[] = {
        llvm::ValueAsMetadata::get(func),
        MDString::get(*llvm_context, "kernel"),
        llvm::ValueAsMetadata::get(tlctx->get_constant(1))};

    MDNode *md_node = MDNode::get(*llvm_context, md_args);

    module->getOrInsertNamedMetadata("nvvm.annotations")->addOperand(md_node);

    auto ptx = compile_module_to_ptx(module);
    auto cuda_kernel = cuda_context.compile(ptx, kernel_name);
    return [=](Context context) {
      cuda_context.launch(cuda_kernel, &context, kernel_grid_dim,
                          kernel_block_dim);
    };
#else
    TC_NOT_IMPLEMENTED;
    return nullptr;
#endif
  }

  void visit(PrintStmt *stmt) override {
    TC_ASSERT(stmt->width() == 1);

    auto value_type = tlctx->get_data_type(stmt->stmt->ret_type.data_type);

    std::string format;

    auto value = stmt->stmt->value;

    if (stmt->stmt->ret_type.data_type == DataType::i32) {
      format = "%d";
    } else if (stmt->stmt->ret_type.data_type == DataType::f32) {
      value_type = llvm::Type::getDoubleTy(*llvm_context);
      value = builder->CreateFPExt(value, value_type);
      format = "%f";
    } else if (stmt->stmt->ret_type.data_type == DataType::f64) {
      format = "%f";
    } else {
      TC_NOT_IMPLEMENTED
    }

    std::vector<llvm::Type *> types{value_type};
    auto stype = llvm::StructType::get(*llvm_context, types, false);
    auto values = builder->CreateAlloca(stype);
    auto value_ptr = builder->CreateGEP(
        values, {tlctx->get_constant(0), tlctx->get_constant(0)});
    builder->CreateStore(value, value_ptr);

    auto format_str = "[debug] " + stmt->str + " = " + format + "\n";

    stmt->value = ModuleBuilder::call(
        builder, "vprintf",
        builder->CreateGlobalStringPtr(format_str, "format_string"),
        builder->CreateBitCast(values,
                               llvm::Type::getInt8PtrTy(*llvm_context)));
  }

  void visit(RangeForStmt *for_stmt) override {
    if (offloaded) {
      create_naive_range_for(for_stmt);
    } else {
      offloaded = true;
      auto loop_begin = for_stmt->begin->as<ConstStmt>()->val[0].val_int32();
      auto loop_end = for_stmt->end->as<ConstStmt>()->val[0].val_int32();
      auto loop_block_dim = for_stmt->block_size;
      if (loop_block_dim == 0) {
        loop_block_dim = default_gpu_block_size;
      }
      kernel_grid_dim =
          (loop_end - loop_begin + loop_block_dim - 1) / loop_block_dim;
      kernel_block_dim = loop_block_dim;
      BasicBlock *body = BasicBlock::Create(*llvm_context, "loop_body", func);
      BasicBlock *after_loop = BasicBlock::Create(*llvm_context, "block", func);

      auto threadIdx =
          builder->CreateIntrinsic(Intrinsic::nvvm_read_ptx_sreg_tid_x, {}, {});
      auto blockIdx = builder->CreateIntrinsic(
          Intrinsic::nvvm_read_ptx_sreg_ctaid_x, {}, {});
      auto blockDim = builder->CreateIntrinsic(
          Intrinsic::nvvm_read_ptx_sreg_ntid_x, {}, {});

      auto loop_id = builder->CreateAdd(
          for_stmt->begin->value,
          builder->CreateAdd(threadIdx,
                             builder->CreateMul(blockIdx, blockDim)));

      builder->CreateStore(loop_id, for_stmt->loop_var->value);

      auto cond = builder->CreateICmp(
          llvm::CmpInst::Predicate::ICMP_SLT,
          builder->CreateLoad(for_stmt->loop_var->value), for_stmt->end->value);

      builder->CreateCondBr(cond, body, after_loop);
      {
        // body cfg
        builder->SetInsertPoint(body);
        for_stmt->body->accept(this);
        builder->CreateBr(after_loop);
      }

      // create_increment(for_stmt->loop_var->value, tlctx->get_constant(1));

      builder->SetInsertPoint(after_loop);
      // builder->CreateRetVoid();

      offloaded = false;
    }
  }
};

FunctionType GPUCodeGen::codegen_llvm() {
  return CodeGenLLVMGPU(this, kernel).gen();
}

#else

FunctionType GPUCodeGen::codegen_llvm() {
  TC_ERROR("LLVM not found");
}

#endif

TLANG_NAMESPACE_END
<|endoftext|>


<commit_before>//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a diagnostic client adaptor that performs rewrites as
// suggested by code modification hints attached to diagnostics. It
// then forwards any diagnostics to the adapted diagnostic client.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/FixItRewriter.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/ADT/OwningPtr.h"
#include <cstdio>

using namespace clang;

FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
                             const LangOptions &LangOpts,
                             FixItPathRewriter *PathRewriter)
  : Diags(Diags),
    Rewrite(SourceMgr, LangOpts),
    PathRewriter(PathRewriter),
    NumFailures(0) {
  Client = Diags.getClient();
  Diags.setClient(this);
}

FixItRewriter::~FixItRewriter() {
  Diags.setClient(Client);
}

bool FixItRewriter::WriteFixedFile(FileID ID, llvm::raw_ostream &OS) {
  const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(ID);
  if (!RewriteBuf) return true;
  RewriteBuf->write(OS);
  OS.flush();
  return false;
}

bool FixItRewriter::WriteFixedFiles() {
  if (NumFailures > 0) {
    Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
    return true;
  }

  for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
    const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
    std::string Filename = Entry->getName();
    if (PathRewriter)
      Filename = PathRewriter->RewriteFilename(Filename);
    std::string Err;
    llvm::raw_fd_ostream OS(Filename.c_str(), Err,
                            llvm::raw_fd_ostream::F_Binary);
    if (!Err.empty()) {
      Diags.Report(clang::diag::err_fe_unable_to_open_output)
          << Filename << Err;
      continue;
    }
    RewriteBuffer &RewriteBuf = I->second;
    OS << std::string(RewriteBuf.begin(), RewriteBuf.end());
    OS.flush();
  }

  return false;
}

bool FixItRewriter::IncludeInDiagnosticCounts() const {
  return Client ? Client->IncludeInDiagnosticCounts() : true;
}

void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
                                     const DiagnosticInfo &Info) {
  Client->HandleDiagnostic(DiagLevel, Info);

  // Skip over any diagnostics that are ignored or notes.
  if (DiagLevel <= Diagnostic::Note)
    return;

  // Make sure that we can perform all of the modifications we
  // in this diagnostic.
  bool CanRewrite = Info.getNumFixItHints() > 0;
  for (unsigned Idx = 0, Last = Info.getNumFixItHints();
       Idx < Last; ++Idx) {
    const FixItHint &Hint = Info.getFixItHint(Idx);
    if (Hint.RemoveRange.isValid() &&
        Rewrite.getRangeSize(Hint.RemoveRange) == -1) {
      CanRewrite = false;
      break;
    }

    if (Hint.InsertionLoc.isValid() &&
        !Rewrite.isRewritable(Hint.InsertionLoc)) {
      CanRewrite = false;
      break;
    }
  }

  if (!CanRewrite) {
    if (Info.getNumFixItHints() > 0)
      Diag(Info.getLocation(), diag::note_fixit_in_macro);

    // If this was an error, refuse to perform any rewriting.
    if (DiagLevel == Diagnostic::Error || DiagLevel == Diagnostic::Fatal) {
      if (++NumFailures == 1)
        Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
    }
    return;
  }

  bool Failed = false;
  for (unsigned Idx = 0, Last = Info.getNumFixItHints();
       Idx < Last; ++Idx) {
    const FixItHint &Hint = Info.getFixItHint(Idx);
    if (!Hint.RemoveRange.isValid()) {
      // We're adding code.
      if (Rewrite.InsertTextBefore(Hint.InsertionLoc, Hint.CodeToInsert))
        Failed = true;
      continue;
    }

    if (Hint.CodeToInsert.empty()) {
      // We're removing code.
      if (Rewrite.RemoveText(Hint.RemoveRange.getBegin(),
                             Rewrite.getRangeSize(Hint.RemoveRange)))
        Failed = true;
      continue;
    }

    // We're replacing code.
    if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(),
                            Rewrite.getRangeSize(Hint.RemoveRange),
                            Hint.CodeToInsert))
      Failed = true;
  }

  if (Failed) {
    ++NumFailures;
    Diag(Info.getLocation(), diag::note_fixit_failed);
    return;
  }

  Diag(Info.getLocation(), diag::note_fixit_applied);
}

/// \brief Emit a diagnostic via the adapted diagnostic client.
void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {
  // When producing this diagnostic, we temporarily bypass ourselves,
  // clear out any current diagnostic, and let the downstream client
  // format the diagnostic.
  Diags.setClient(Client);
  Diags.Clear();
  Diags.Report(Loc, DiagID);
  Diags.setClient(this);
}

FixItPathRewriter::~FixItPathRewriter() {}
<commit_msg>Switch this to new API.<commit_after>//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a diagnostic client adaptor that performs rewrites as
// suggested by code modification hints attached to diagnostics. It
// then forwards any diagnostics to the adapted diagnostic client.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/FixItRewriter.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/ADT/OwningPtr.h"
#include <cstdio>

using namespace clang;

FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
                             const LangOptions &LangOpts,
                             FixItPathRewriter *PathRewriter)
  : Diags(Diags),
    Rewrite(SourceMgr, LangOpts),
    PathRewriter(PathRewriter),
    NumFailures(0) {
  Client = Diags.getClient();
  Diags.setClient(this);
}

FixItRewriter::~FixItRewriter() {
  Diags.setClient(Client);
}

bool FixItRewriter::WriteFixedFile(FileID ID, llvm::raw_ostream &OS) {
  const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(ID);
  if (!RewriteBuf) return true;
  RewriteBuf->write(OS);
  OS.flush();
  return false;
}

bool FixItRewriter::WriteFixedFiles() {
  if (NumFailures > 0) {
    Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
    return true;
  }

  for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
    const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
    std::string Filename = Entry->getName();
    if (PathRewriter)
      Filename = PathRewriter->RewriteFilename(Filename);
    std::string Err;
    llvm::raw_fd_ostream OS(Filename.c_str(), Err,
                            llvm::raw_fd_ostream::F_Binary);
    if (!Err.empty()) {
      Diags.Report(clang::diag::err_fe_unable_to_open_output)
          << Filename << Err;
      continue;
    }
    RewriteBuffer &RewriteBuf = I->second;
    RewriteBuf.write(OS);
    OS.flush();
  }

  return false;
}

bool FixItRewriter::IncludeInDiagnosticCounts() const {
  return Client ? Client->IncludeInDiagnosticCounts() : true;
}

void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
                                     const DiagnosticInfo &Info) {
  Client->HandleDiagnostic(DiagLevel, Info);

  // Skip over any diagnostics that are ignored or notes.
  if (DiagLevel <= Diagnostic::Note)
    return;

  // Make sure that we can perform all of the modifications we
  // in this diagnostic.
  bool CanRewrite = Info.getNumFixItHints() > 0;
  for (unsigned Idx = 0, Last = Info.getNumFixItHints();
       Idx < Last; ++Idx) {
    const FixItHint &Hint = Info.getFixItHint(Idx);
    if (Hint.RemoveRange.isValid() &&
        Rewrite.getRangeSize(Hint.RemoveRange) == -1) {
      CanRewrite = false;
      break;
    }

    if (Hint.InsertionLoc.isValid() &&
        !Rewrite.isRewritable(Hint.InsertionLoc)) {
      CanRewrite = false;
      break;
    }
  }

  if (!CanRewrite) {
    if (Info.getNumFixItHints() > 0)
      Diag(Info.getLocation(), diag::note_fixit_in_macro);

    // If this was an error, refuse to perform any rewriting.
    if (DiagLevel == Diagnostic::Error || DiagLevel == Diagnostic::Fatal) {
      if (++NumFailures == 1)
        Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
    }
    return;
  }

  bool Failed = false;
  for (unsigned Idx = 0, Last = Info.getNumFixItHints();
       Idx < Last; ++Idx) {
    const FixItHint &Hint = Info.getFixItHint(Idx);
    if (!Hint.RemoveRange.isValid()) {
      // We're adding code.
      if (Rewrite.InsertTextBefore(Hint.InsertionLoc, Hint.CodeToInsert))
        Failed = true;
      continue;
    }

    if (Hint.CodeToInsert.empty()) {
      // We're removing code.
      if (Rewrite.RemoveText(Hint.RemoveRange.getBegin(),
                             Rewrite.getRangeSize(Hint.RemoveRange)))
        Failed = true;
      continue;
    }

    // We're replacing code.
    if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(),
                            Rewrite.getRangeSize(Hint.RemoveRange),
                            Hint.CodeToInsert))
      Failed = true;
  }

  if (Failed) {
    ++NumFailures;
    Diag(Info.getLocation(), diag::note_fixit_failed);
    return;
  }

  Diag(Info.getLocation(), diag::note_fixit_applied);
}

/// \brief Emit a diagnostic via the adapted diagnostic client.
void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {
  // When producing this diagnostic, we temporarily bypass ourselves,
  // clear out any current diagnostic, and let the downstream client
  // format the diagnostic.
  Diags.setClient(Client);
  Diags.Clear();
  Diags.Report(Loc, DiagID);
  Diags.setClient(this);
}

FixItPathRewriter::~FixItPathRewriter() {}
<|endoftext|>


<commit_before>//===-- LCSSA.cpp - Convert loops into loop-closed SSA form ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Owen Anderson and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass transforms loops by placing phi nodes at the end of the loops for
// all values that are live across the loop boundary.  For example, it turns
// the left into the right code:
//
// for (...)                for (...)
//   if (c)                   if (c)
//     X1 = ...                 X1 = ...
//   else                     else
//     X2 = ...                 X2 = ...
//   X3 = phi(X1, X2)         X3 = phi(X1, X2)
// ... = X3 + 4              X4 = phi(X3)
//                           ... = X4 + 4
//
// This is still valid LLVM; the extra phi nodes are purely redundant, and will
// be trivially eliminated by InstCombine.  The major benefit of this
// transformation is that it makes many other loop optimizations, such as
// LoopUnswitching, simpler.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "lcssa"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <map>
using namespace llvm;

STATISTIC(NumLCSSA, "Number of live out of a loop variables");

namespace {
  struct VISIBILITY_HIDDEN LCSSA : public LoopPass {
    static char ID; // Pass identification, replacement for typeid
    LCSSA() : LoopPass((intptr_t)&ID) {}

    // Cached analysis information for the current function.
    LoopInfo *LI;
    DominatorTree *DT;
    std::vector<BasicBlock*> LoopBlocks;

    virtual bool runOnLoop(Loop *L, LPPassManager &LPM);

    void ProcessInstruction(Instruction* Instr,
                            const std::vector<BasicBlock*>& exitBlocks);

    /// This transformation requires natural loop information & requires that
    /// loop preheaders be inserted into the CFG.  It maintains both of these,
    /// as well as the CFG.  It also requires dominator information.
    ///
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.addRequired<LoopInfo>();
      AU.addPreserved<LoopInfo>();
      AU.addRequired<DominatorTree>();
      AU.addPreserved<ScalarEvolution>();
    }
  private:
    void getLoopValuesUsedOutsideLoop(Loop *L,
                                      SetVector<Instruction*> &AffectedValues);

    Value *GetValueForBlock(DomTreeNode *BB, Instruction *OrigInst,
                            std::map<DomTreeNode*, Value*> &Phis);

    /// inLoop - returns true if the given block is within the current loop
    const bool inLoop(BasicBlock* B) {
      return std::binary_search(LoopBlocks.begin(), LoopBlocks.end(), B);
    }
  };

  char LCSSA::ID = 0;
  RegisterPass<LCSSA> X("lcssa", "Loop-Closed SSA Form Pass");
}

LoopPass *llvm::createLCSSAPass() { return new LCSSA(); }
const PassInfo *llvm::LCSSAID = X.getPassInfo();

/// runOnFunction - Process all loops in the function, inner-most out.
bool LCSSA::runOnLoop(Loop *L, LPPassManager &LPM) {

  LI = &LPM.getAnalysis<LoopInfo>();
  DT = &getAnalysis<DominatorTree>();

  // Speed up queries by creating a sorted list of blocks
  LoopBlocks.clear();
  LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end());
  std::sort(LoopBlocks.begin(), LoopBlocks.end());

  SetVector<Instruction*> AffectedValues;
  getLoopValuesUsedOutsideLoop(L, AffectedValues);

  // If no values are affected, we can save a lot of work, since we know that
  // nothing will be changed.
  if (AffectedValues.empty())
    return false;

  std::vector<BasicBlock*> exitBlocks;
  L->getExitBlocks(exitBlocks);

  // Iterate over all affected values for this loop and insert Phi nodes
  // for them in the appropriate exit blocks

  for (SetVector<Instruction*>::iterator I = AffectedValues.begin(),
       E = AffectedValues.end(); I != E; ++I)
    ProcessInstruction(*I, exitBlocks);

  assert(L->isLCSSAForm());

  return true;
}

/// processInstruction - Given a live-out instruction, insert LCSSA Phi nodes,
/// eliminate all out-of-loop uses.
void LCSSA::ProcessInstruction(Instruction *Instr,
                               const std::vector<BasicBlock*>& exitBlocks) {
  ++NumLCSSA; // We are applying the transformation

  // Keep track of the blocks that have the value available already.
  std::map<DomTreeNode*, Value*> Phis;

  DomTreeNode *InstrNode = DT->getNode(Instr->getParent());

  // Insert the LCSSA phi's into the exit blocks (dominated by the value), and
  // add them to the Phi's map.
  for (std::vector<BasicBlock*>::const_iterator BBI = exitBlocks.begin(),
      BBE = exitBlocks.end(); BBI != BBE; ++BBI) {
    BasicBlock *BB = *BBI;
    DomTreeNode *ExitBBNode = DT->getNode(BB);
    Value *&Phi = Phis[ExitBBNode];
    if (!Phi && DT->dominates(InstrNode, ExitBBNode)) {
      PHINode *PN = new PHINode(Instr->getType(), Instr->getName()+".lcssa",
                                BB->begin());
      PN->reserveOperandSpace(std::distance(pred_begin(BB), pred_end(BB)));

      // Remember that this phi makes the value alive in this block.
      Phi = PN;

      // Add inputs from inside the loop for this PHI.
      for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
        PN->addIncoming(Instr, *PI);
    }
  }

  // Record all uses of Instr outside the loop.  We need to rewrite these.  The
  // LCSSA phis won't be included because they use the value in the loop.
  for (Value::use_iterator UI = Instr->use_begin(), E = Instr->use_end();
       UI != E;) {
    BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
    if (PHINode *P = dyn_cast<PHINode>(*UI)) {
      unsigned OperandNo = UI.getOperandNo();
      UserBB = P->getIncomingBlock(OperandNo/2);
    }

    // If the user is in the loop, don't rewrite it!
    if (UserBB == Instr->getParent() || inLoop(UserBB)) {
      ++UI;
      continue;
    }

    // Otherwise, patch up uses of the value with the appropriate LCSSA Phi,
    // inserting PHI nodes into join points where needed.
    Value *Val = GetValueForBlock(DT->getNode(UserBB), Instr, Phis);

    // Preincrement the iterator to avoid invalidating it when we change the
    // value.
    Use &U = UI.getUse();
    ++UI;
    U.set(Val);
  }
}

/// getLoopValuesUsedOutsideLoop - Return any values defined in the loop that
/// are used by instructions outside of it.
void LCSSA::getLoopValuesUsedOutsideLoop(Loop *L,
                                      SetVector<Instruction*> &AffectedValues) {
  // FIXME: For large loops, we may be able to avoid a lot of use-scanning
  // by using dominance information.  In particular, if a block does not
  // dominate any of the loop exits, then none of the values defined in the
  // block could be used outside the loop.
  for (Loop::block_iterator BB = L->block_begin(), E = L->block_end();
       BB != E; ++BB) {
    for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E; ++I)
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI) {
        BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
        if (PHINode* p = dyn_cast<PHINode>(*UI)) {
          unsigned OperandNo = UI.getOperandNo();
          UserBB = p->getIncomingBlock(OperandNo/2);
        }

        if (*BB != UserBB && !inLoop(UserBB)) {
          AffectedValues.insert(I);
          break;
        }
      }
  }
}

/// GetValueForBlock - Get the value to use within the specified basic block.
/// available values are in Phis.
Value *LCSSA::GetValueForBlock(DomTreeNode *BB, Instruction *OrigInst,
                               std::map<DomTreeNode*, Value*> &Phis) {
  // If there is no dominator info for this BB, it is unreachable.
  if (BB == 0)
    return UndefValue::get(OrigInst->getType());

  // If we have already computed this value, return the previously computed val.
  Value *&V = Phis[BB];
  if (V) return V;

  DomTreeNode *IDom = BB->getIDom();

  // Otherwise, there are two cases: we either have to insert a PHI node or we
  // don't.  We need to insert a PHI node if this block is not dominated by one
  // of the exit nodes from the loop (the loop could have multiple exits, and
  // though the value defined *inside* the loop dominated all its uses, each
  // exit by itself may not dominate all the uses).
  //
  // The simplest way to check for this condition is by checking to see if the
  // idom is in the loop.  If so, we *know* that none of the exit blocks
  // dominate this block.  Note that we *know* that the block defining the
  // original instruction is in the idom chain, because if it weren't, then the
  // original value didn't dominate this use.
  if (!inLoop(IDom->getBlock())) {
    // Idom is not in the loop, we must still be "below" the exit block and must
    // be fully dominated by the value live in the idom.
    return V = GetValueForBlock(IDom, OrigInst, Phis);
  }

  BasicBlock *BBN = BB->getBlock();

  // Otherwise, the idom is the loop, so we need to insert a PHI node.  Do so
  // now, then get values to fill in the incoming values for the PHI.
  PHINode *PN = new PHINode(OrigInst->getType(), OrigInst->getName()+".lcssa",
                            BBN->begin());
  PN->reserveOperandSpace(std::distance(pred_begin(BBN), pred_end(BBN)));
  V = PN;

  // Fill in the incoming values for the block.
  for (pred_iterator PI = pred_begin(BBN), E = pred_end(BBN); PI != E; ++PI)
    PN->addIncoming(GetValueForBlock(DT->getNode(*PI), OrigInst, Phis), *PI);
  return PN;
}

<commit_msg>LCSSA preserves dom info.<commit_after>//===-- LCSSA.cpp - Convert loops into loop-closed SSA form ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Owen Anderson and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass transforms loops by placing phi nodes at the end of the loops for
// all values that are live across the loop boundary.  For example, it turns
// the left into the right code:
//
// for (...)                for (...)
//   if (c)                   if (c)
//     X1 = ...                 X1 = ...
//   else                     else
//     X2 = ...                 X2 = ...
//   X3 = phi(X1, X2)         X3 = phi(X1, X2)
// ... = X3 + 4              X4 = phi(X3)
//                           ... = X4 + 4
//
// This is still valid LLVM; the extra phi nodes are purely redundant, and will
// be trivially eliminated by InstCombine.  The major benefit of this
// transformation is that it makes many other loop optimizations, such as
// LoopUnswitching, simpler.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "lcssa"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <map>
using namespace llvm;

STATISTIC(NumLCSSA, "Number of live out of a loop variables");

namespace {
  struct VISIBILITY_HIDDEN LCSSA : public LoopPass {
    static char ID; // Pass identification, replacement for typeid
    LCSSA() : LoopPass((intptr_t)&ID) {}

    // Cached analysis information for the current function.
    LoopInfo *LI;
    DominatorTree *DT;
    std::vector<BasicBlock*> LoopBlocks;

    virtual bool runOnLoop(Loop *L, LPPassManager &LPM);

    void ProcessInstruction(Instruction* Instr,
                            const std::vector<BasicBlock*>& exitBlocks);

    /// This transformation requires natural loop information & requires that
    /// loop preheaders be inserted into the CFG.  It maintains both of these,
    /// as well as the CFG.  It also requires dominator information.
    ///
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.addRequired<LoopInfo>();
      AU.addPreserved<LoopInfo>();
      AU.addRequired<DominatorTree>();
      AU.addPreserved<ScalarEvolution>();
      AU.addPreserved<DominatorTree>();

      // Request DominanceFrontier now, even though LCSSA does
      // not use it. This allows Pass Manager to schedule Dominance
      // Frontier early enough such that one LPPassManager can handle
      // multiple loop transformation passes.
      AU.addRequired<DominanceFrontier>();
      AU.addPreserved<DominanceFrontier>();
    }
  private:
    void getLoopValuesUsedOutsideLoop(Loop *L,
                                      SetVector<Instruction*> &AffectedValues);

    Value *GetValueForBlock(DomTreeNode *BB, Instruction *OrigInst,
                            std::map<DomTreeNode*, Value*> &Phis);

    /// inLoop - returns true if the given block is within the current loop
    const bool inLoop(BasicBlock* B) {
      return std::binary_search(LoopBlocks.begin(), LoopBlocks.end(), B);
    }
  };

  char LCSSA::ID = 0;
  RegisterPass<LCSSA> X("lcssa", "Loop-Closed SSA Form Pass");
}

LoopPass *llvm::createLCSSAPass() { return new LCSSA(); }
const PassInfo *llvm::LCSSAID = X.getPassInfo();

/// runOnFunction - Process all loops in the function, inner-most out.
bool LCSSA::runOnLoop(Loop *L, LPPassManager &LPM) {

  LI = &LPM.getAnalysis<LoopInfo>();
  DT = &getAnalysis<DominatorTree>();

  // Speed up queries by creating a sorted list of blocks
  LoopBlocks.clear();
  LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end());
  std::sort(LoopBlocks.begin(), LoopBlocks.end());

  SetVector<Instruction*> AffectedValues;
  getLoopValuesUsedOutsideLoop(L, AffectedValues);

  // If no values are affected, we can save a lot of work, since we know that
  // nothing will be changed.
  if (AffectedValues.empty())
    return false;

  std::vector<BasicBlock*> exitBlocks;
  L->getExitBlocks(exitBlocks);

  // Iterate over all affected values for this loop and insert Phi nodes
  // for them in the appropriate exit blocks

  for (SetVector<Instruction*>::iterator I = AffectedValues.begin(),
       E = AffectedValues.end(); I != E; ++I)
    ProcessInstruction(*I, exitBlocks);

  assert(L->isLCSSAForm());

  return true;
}

/// processInstruction - Given a live-out instruction, insert LCSSA Phi nodes,
/// eliminate all out-of-loop uses.
void LCSSA::ProcessInstruction(Instruction *Instr,
                               const std::vector<BasicBlock*>& exitBlocks) {
  ++NumLCSSA; // We are applying the transformation

  // Keep track of the blocks that have the value available already.
  std::map<DomTreeNode*, Value*> Phis;

  DomTreeNode *InstrNode = DT->getNode(Instr->getParent());

  // Insert the LCSSA phi's into the exit blocks (dominated by the value), and
  // add them to the Phi's map.
  for (std::vector<BasicBlock*>::const_iterator BBI = exitBlocks.begin(),
      BBE = exitBlocks.end(); BBI != BBE; ++BBI) {
    BasicBlock *BB = *BBI;
    DomTreeNode *ExitBBNode = DT->getNode(BB);
    Value *&Phi = Phis[ExitBBNode];
    if (!Phi && DT->dominates(InstrNode, ExitBBNode)) {
      PHINode *PN = new PHINode(Instr->getType(), Instr->getName()+".lcssa",
                                BB->begin());
      PN->reserveOperandSpace(std::distance(pred_begin(BB), pred_end(BB)));

      // Remember that this phi makes the value alive in this block.
      Phi = PN;

      // Add inputs from inside the loop for this PHI.
      for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
        PN->addIncoming(Instr, *PI);
    }
  }

  // Record all uses of Instr outside the loop.  We need to rewrite these.  The
  // LCSSA phis won't be included because they use the value in the loop.
  for (Value::use_iterator UI = Instr->use_begin(), E = Instr->use_end();
       UI != E;) {
    BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
    if (PHINode *P = dyn_cast<PHINode>(*UI)) {
      unsigned OperandNo = UI.getOperandNo();
      UserBB = P->getIncomingBlock(OperandNo/2);
    }

    // If the user is in the loop, don't rewrite it!
    if (UserBB == Instr->getParent() || inLoop(UserBB)) {
      ++UI;
      continue;
    }

    // Otherwise, patch up uses of the value with the appropriate LCSSA Phi,
    // inserting PHI nodes into join points where needed.
    Value *Val = GetValueForBlock(DT->getNode(UserBB), Instr, Phis);

    // Preincrement the iterator to avoid invalidating it when we change the
    // value.
    Use &U = UI.getUse();
    ++UI;
    U.set(Val);
  }
}

/// getLoopValuesUsedOutsideLoop - Return any values defined in the loop that
/// are used by instructions outside of it.
void LCSSA::getLoopValuesUsedOutsideLoop(Loop *L,
                                      SetVector<Instruction*> &AffectedValues) {
  // FIXME: For large loops, we may be able to avoid a lot of use-scanning
  // by using dominance information.  In particular, if a block does not
  // dominate any of the loop exits, then none of the values defined in the
  // block could be used outside the loop.
  for (Loop::block_iterator BB = L->block_begin(), E = L->block_end();
       BB != E; ++BB) {
    for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E; ++I)
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI) {
        BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
        if (PHINode* p = dyn_cast<PHINode>(*UI)) {
          unsigned OperandNo = UI.getOperandNo();
          UserBB = p->getIncomingBlock(OperandNo/2);
        }

        if (*BB != UserBB && !inLoop(UserBB)) {
          AffectedValues.insert(I);
          break;
        }
      }
  }
}

/// GetValueForBlock - Get the value to use within the specified basic block.
/// available values are in Phis.
Value *LCSSA::GetValueForBlock(DomTreeNode *BB, Instruction *OrigInst,
                               std::map<DomTreeNode*, Value*> &Phis) {
  // If there is no dominator info for this BB, it is unreachable.
  if (BB == 0)
    return UndefValue::get(OrigInst->getType());

  // If we have already computed this value, return the previously computed val.
  Value *&V = Phis[BB];
  if (V) return V;

  DomTreeNode *IDom = BB->getIDom();

  // Otherwise, there are two cases: we either have to insert a PHI node or we
  // don't.  We need to insert a PHI node if this block is not dominated by one
  // of the exit nodes from the loop (the loop could have multiple exits, and
  // though the value defined *inside* the loop dominated all its uses, each
  // exit by itself may not dominate all the uses).
  //
  // The simplest way to check for this condition is by checking to see if the
  // idom is in the loop.  If so, we *know* that none of the exit blocks
  // dominate this block.  Note that we *know* that the block defining the
  // original instruction is in the idom chain, because if it weren't, then the
  // original value didn't dominate this use.
  if (!inLoop(IDom->getBlock())) {
    // Idom is not in the loop, we must still be "below" the exit block and must
    // be fully dominated by the value live in the idom.
    return V = GetValueForBlock(IDom, OrigInst, Phis);
  }

  BasicBlock *BBN = BB->getBlock();

  // Otherwise, the idom is the loop, so we need to insert a PHI node.  Do so
  // now, then get values to fill in the incoming values for the PHI.
  PHINode *PN = new PHINode(OrigInst->getType(), OrigInst->getName()+".lcssa",
                            BBN->begin());
  PN->reserveOperandSpace(std::distance(pred_begin(BBN), pred_end(BBN)));
  V = PN;

  // Fill in the incoming values for the block.
  for (pred_iterator PI = pred_begin(BBN), E = pred_end(BBN); PI != E; ++PI)
    PN->addIncoming(GetValueForBlock(DT->getNode(*PI), OrigInst, Phis), *PI);
  return PN;
}

<|endoftext|>


<commit_before>#include <vector>

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QString>
#include <QStandardItemModel>
#include <QAction>
#include <QMenu>
#include <QHeaderView>
#include <QTimer>

#include "common.h"
#include "event.h"
#include "task_board.h"

namespace Plow {
namespace Gui {

QStringList TaskBoardModel::HeaderLabels = QStringList()
    << "Name"
    << "State"
    << "Node"
    << "Duration"
    << "Log";

const int COLUMNS = 5;

// Return this rather than creating empty variants
// all the time.
const QVariant EMPTY_VARIANT;

/* TaskBoardWidget
**------------------------------------------------*/

TaskBoardWidget::TaskBoardWidget(QWidget* parent) :
    QWidget(parent),
    m_filter(new TaskFilterT()),
    m_layers(new QPushButton(this)),
    m_states(new QPushButton(this)),
    m_job_name(new QLabel(this)),
    m_view(new TaskBoardView(this))
{
    m_layers->setText("Layers");
    m_layers->setMenu(new QMenu(this));

    m_states->setText("States");
    m_states->setMenu(new QMenu(this));

    m_view->horizontalHeader()->setStretchLastSection(true);

    std::map<int, const char*>::const_iterator iter;
    for (iter = _TaskState_VALUES_TO_NAMES.begin();
         iter != _TaskState_VALUES_TO_NAMES.end(); ++iter)
    {
        QAction* action = new QAction(
            QString(iter->second), m_states->menu());
        action->setData(iter->first);
        action->setCheckable(true);
        m_states->menu()->addAction(action);
    }

    QHBoxLayout* ctl_layout = new QHBoxLayout();
    ctl_layout->addWidget(m_layers);
    ctl_layout->addWidget(m_states);
    ctl_layout->addStretch();
    ctl_layout->addWidget(m_job_name);

    QVBoxLayout* layout = new QVBoxLayout(this);
    layout->addLayout(ctl_layout);
    layout->addWidget(m_view);

    connect(EventManager::getInstance(), SIGNAL(jobSelected(QString)),
        this, SLOT(handleJobSelected(QString)));

    m_model = 0;
    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(refreshModel()));
}

TaskBoardWidget::~TaskBoardWidget()
{
    delete m_timer;
}

void TaskBoardWidget::refreshModel()
{
    if (m_model)
    {
        m_model->refresh();
    }
}

void TaskBoardWidget::handleJobSelected(const QString& id)
{
    JobT job;
    getJobById(job, id.toStdString());
    setJob(job);
}

void  TaskBoardWidget::setJob(const JobT& job)
{
    // Stop the timer
    m_timer->stop();

    std::vector<LayerT> layers;
    Plow::getLayers(layers, job);

    // Update the layer display
    m_layers->menu()->clear();
    for (int r = 0; r < layers.size(); ++r)
    {
        QAction* action = new QAction(
            QString::fromStdString(layers[r].name), m_layers->menu());
        action->setCheckable(true);
        m_layers->menu()->addAction(action);
    }

    // Set up a new model
    m_filter->jobId = job.id;
    TaskBoardModel* model = new TaskBoardModel(*m_filter, this);
    model->init();

    m_job_name->setText(QString::fromStdString(job.name));
    m_view->setModel(model);
    m_view->setColumnWidth(0, 350);

    // If we have an old model set, delete it.
    if (m_model) {
        delete m_model;
        m_model = 0;
    }

    // Set the model and restart the timer.
    m_model = model;
    m_timer->start(3000);
}

TaskFilterT* TaskBoardWidget::getTaskFilter() const
{
    return m_filter;
}

/* TaskBoardView
**------------------------------------------------*/

TaskBoardView::TaskBoardView(QWidget* parent) :
    QTableView(parent)
{

    connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
        this, SLOT(taskDoubleClickedHandler(const QModelIndex&)));
}

TaskBoardView::~TaskBoardView()
{

}

void TaskBoardView::taskDoubleClickedHandler(const QModelIndex& index)
{
    QString taskId = model()->data(index, Qt::UserRole).toString();
    //TODO: add log file viewer.
}

/* TaskBoardModel
**------------------------------------------------*/

TaskBoardModel::TaskBoardModel(TaskFilterT filter, QObject* parent) :
    QAbstractTableModel(parent),
    m_filter(filter)
{

}

TaskBoardModel::~TaskBoardModel()
{
    m_timer->stop();
    delete m_timer;
}

void TaskBoardModel::init()
{
    uint64_t qtime = getPlowTime();

    getTasks(m_tasks, m_filter);
    m_filter.lastUpdateTime = qtime;

    for(int i=0; i<m_tasks.size(); i++) {
        m_index[m_tasks[i].id] = i;
    }

    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(refreshRunningTime()));
    m_timer->start(1000);
}

void TaskBoardModel::refresh()
{

    // Get the time from the server.
    uint64_t plow_time = getPlowTime();

    // Make a query to get the tasks since the last update time.
    std::vector<TaskT> updated;
    getTasks(updated, m_filter);

    // Set the update time for the next query;
    m_filter.lastUpdateTime = plow_time;

    std::vector<TaskT>::iterator iter;
    for (iter = updated.begin(); iter != updated.end(); ++iter)
    {
        int idx = m_index[iter->id];
        m_tasks[idx] = *iter;
        emit dataChanged(index(idx, 0), index(idx, COLUMNS-1));
    }
}

void TaskBoardModel::refreshRunningTime()
{
    std::vector<TaskT>::iterator iter;
    for (iter = m_tasks.begin(); iter != m_tasks.end(); ++iter)
    {
        if (iter->state == TaskState::RUNNING)
        {
            emit dataChanged(index(m_index[iter->id], 0),
                             index(m_index[iter->id], COLUMNS-1));
        }
    }
}

int TaskBoardModel::rowCount(const QModelIndex& parent) const
{
    return m_tasks.size();
}

int TaskBoardModel::columnCount (const QModelIndex& parent) const
{
    return COLUMNS;
}

QVariant TaskBoardModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation != Qt::Horizontal) {
        return EMPTY_VARIANT;

    }
    switch(role)
    {
    case Qt::DisplayRole:
        return TaskBoardModel::HeaderLabels[section];
    }

    return EMPTY_VARIANT;
}

QVariant TaskBoardModel::data (const QModelIndex & index, int role) const
{
    int row = index.row();
    int col = index.column();

    const TaskT& task = m_tasks[row];

    switch(role)
    {

    case Qt::DisplayRole:
        if (col == 0)
        {
            return QString(task.name.c_str());
        }
        else if (col == 1)
        {
            int state = task.state;
            return QString(_TaskState_VALUES_TO_NAMES.find(state)->second);
        }
        else if (col == 2)
        {
            return QString(task.lastNodeName.c_str());
        }
        else if (col == 3)
        {
            std::string duration;
            formatDuration(duration, task.startTime, task.stopTime);
            return QString::fromStdString(duration);
        }
        else if (col == 4) {
            return QString(task.lastLogLine.c_str());
        }
        break;

    case Qt::BackgroundRole:
        if (col == 1)
        {
            int state = task.state;
            return PlowStyle::TaskColors[state];
        }
        break;

    case Qt::UserRole:
        return QString::fromStdString(task.id);

    }

    return EMPTY_VARIANT;
}

} //
} //<commit_msg>Simplified the horizontal header code.<commit_after>#include <vector>

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QString>
#include <QStandardItemModel>
#include <QAction>
#include <QMenu>
#include <QHeaderView>
#include <QTimer>

#include "common.h"
#include "event.h"
#include "task_board.h"

namespace Plow {
namespace Gui {

QStringList TaskBoardModel::HeaderLabels = QStringList()
    << "Name"
    << "State"
    << "Node"
    << "Duration"
    << "Log";

const int COLUMNS = TaskBoardModel::HeaderLabels.size();

// Return this rather than creating empty variants
// all the time.
const QVariant EMPTY_VARIANT;

/* TaskBoardWidget
**------------------------------------------------*/

TaskBoardWidget::TaskBoardWidget(QWidget* parent) :
    QWidget(parent),
    m_filter(new TaskFilterT()),
    m_layers(new QPushButton(this)),
    m_states(new QPushButton(this)),
    m_job_name(new QLabel(this)),
    m_view(new TaskBoardView(this))
{
    m_layers->setText("Layers");
    m_layers->setMenu(new QMenu(this));

    m_states->setText("States");
    m_states->setMenu(new QMenu(this));

    m_view->horizontalHeader()->setStretchLastSection(true);

    std::map<int, const char*>::const_iterator iter;
    for (iter = _TaskState_VALUES_TO_NAMES.begin();
         iter != _TaskState_VALUES_TO_NAMES.end(); ++iter)
    {
        QAction* action = new QAction(
            QString(iter->second), m_states->menu());
        action->setData(iter->first);
        action->setCheckable(true);
        m_states->menu()->addAction(action);
    }

    QHBoxLayout* ctl_layout = new QHBoxLayout();
    ctl_layout->addWidget(m_layers);
    ctl_layout->addWidget(m_states);
    ctl_layout->addStretch();
    ctl_layout->addWidget(m_job_name);

    QVBoxLayout* layout = new QVBoxLayout(this);
    layout->addLayout(ctl_layout);
    layout->addWidget(m_view);

    connect(EventManager::getInstance(), SIGNAL(jobSelected(QString)),
        this, SLOT(handleJobSelected(QString)));

    m_model = 0;
    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(refreshModel()));
}

TaskBoardWidget::~TaskBoardWidget()
{
    delete m_timer;
}

void TaskBoardWidget::refreshModel()
{
    if (m_model)
    {
        m_model->refresh();
    }
}

void TaskBoardWidget::handleJobSelected(const QString& id)
{
    JobT job;
    getJobById(job, id.toStdString());
    setJob(job);
}

void  TaskBoardWidget::setJob(const JobT& job)
{
    // Stop the timer
    m_timer->stop();

    std::vector<LayerT> layers;
    Plow::getLayers(layers, job);

    // Update the layer display
    m_layers->menu()->clear();
    for (int r = 0; r < layers.size(); ++r)
    {
        QAction* action = new QAction(
            QString::fromStdString(layers[r].name), m_layers->menu());
        action->setCheckable(true);
        m_layers->menu()->addAction(action);
    }

    // Set up a new model
    m_filter->jobId = job.id;
    TaskBoardModel* model = new TaskBoardModel(*m_filter, this);
    model->init();

    m_job_name->setText(QString::fromStdString(job.name));
    m_view->setModel(model);
    m_view->setColumnWidth(0, 350);

    // If we have an old model set, delete it.
    if (m_model) {
        delete m_model;
        m_model = 0;
    }

    // Set the model and restart the timer.
    m_model = model;
    m_timer->start(3000);
}

TaskFilterT* TaskBoardWidget::getTaskFilter() const
{
    return m_filter;
}

/* TaskBoardView
**------------------------------------------------*/

TaskBoardView::TaskBoardView(QWidget* parent) :
    QTableView(parent)
{

    connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
        this, SLOT(taskDoubleClickedHandler(const QModelIndex&)));
}

TaskBoardView::~TaskBoardView()
{

}

void TaskBoardView::taskDoubleClickedHandler(const QModelIndex& index)
{
    QString taskId = model()->data(index, Qt::UserRole).toString();
    //TODO: add log file viewer.
}

/* TaskBoardModel
**------------------------------------------------*/

TaskBoardModel::TaskBoardModel(TaskFilterT filter, QObject* parent) :
    QAbstractTableModel(parent),
    m_filter(filter)
{

}

TaskBoardModel::~TaskBoardModel()
{
    m_timer->stop();
    delete m_timer;
}

void TaskBoardModel::init()
{
    uint64_t qtime = getPlowTime();

    getTasks(m_tasks, m_filter);
    m_filter.lastUpdateTime = qtime;

    for(int i=0; i<m_tasks.size(); i++) {
        m_index[m_tasks[i].id] = i;
    }

    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(refreshRunningTime()));
    m_timer->start(1000);
}

void TaskBoardModel::refresh()
{

    // Get the time from the server.
    uint64_t plow_time = getPlowTime();

    // Make a query to get the tasks since the last update time.
    std::vector<TaskT> updated;
    getTasks(updated, m_filter);

    // Set the update time for the next query;
    m_filter.lastUpdateTime = plow_time;

    std::vector<TaskT>::iterator iter;
    for (iter = updated.begin(); iter != updated.end(); ++iter)
    {
        int idx = m_index[iter->id];
        m_tasks[idx] = *iter;
        emit dataChanged(index(idx, 0), index(idx, COLUMNS-1));
    }
}

void TaskBoardModel::refreshRunningTime()
{
    std::vector<TaskT>::iterator iter;
    for (iter = m_tasks.begin(); iter != m_tasks.end(); ++iter)
    {
        if (iter->state == TaskState::RUNNING)
        {
            emit dataChanged(index(m_index[iter->id], 0),
                             index(m_index[iter->id], COLUMNS-1));
        }
    }
}

int TaskBoardModel::rowCount(const QModelIndex& parent) const
{
    return m_tasks.size();
}

int TaskBoardModel::columnCount (const QModelIndex& parent) const
{
    return COLUMNS;
}

QVariant TaskBoardModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
    {
        return TaskBoardModel::HeaderLabels[section];
    }

    return EMPTY_VARIANT;
}

QVariant TaskBoardModel::data (const QModelIndex & index, int role) const
{
    int row = index.row();
    int col = index.column();

    const TaskT& task = m_tasks[row];

    switch(role)
    {

    case Qt::DisplayRole:
        if (col == 0)
        {
            return QString(task.name.c_str());
        }
        else if (col == 1)
        {
            int state = task.state;
            return QString(_TaskState_VALUES_TO_NAMES.find(state)->second);
        }
        else if (col == 2)
        {
            return QString(task.lastNodeName.c_str());
        }
        else if (col == 3)
        {
            std::string duration;
            formatDuration(duration, task.startTime, task.stopTime);
            return QString::fromStdString(duration);
        }
        else if (col == 4) {
            return QString(task.lastLogLine.c_str());
        }
        break;

    case Qt::BackgroundRole:
        if (col == 1)
        {
            int state = task.state;
            return PlowStyle::TaskColors[state];
        }
        break;

    case Qt::UserRole:
        return QString::fromStdString(task.id);

    }

    return EMPTY_VARIANT;
}

} //
} //<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#ifndef PEGTL_TRACE_HH
#define PEGTL_TRACE_HH

#include <iostream>

#include "parse.hh"
#include "normal.hh"
#include "nothing.hh"
#include "position_info.hh"

#include "internal/demangle.hh"

namespace pegtl
{
   template< typename Rule >
   struct tracer
         : normal< Rule >
   {
      template< typename Input, typename ... States >
      static void start( const Input & in, States && ... )
      {
         std::cerr << position_info( in ) << "  start  " << internal::demangle< Rule >() << std::endl;
      }

      template< typename Input, typename ... States >
      static void success( const Input & in, States && ... )
      {
         std::cerr << position_info( in ) << " success " << internal::demangle< Rule >() << std::endl;
      }

      template< typename Input, typename ... States >
      static void failure( const Input & in, States && ... )
      {
         std::cerr << position_info( in ) << " failure " << internal::demangle< Rule >() << std::endl;
      }
   };

   template< typename Rule, template< typename ... > class Action = nothing, typename ... Args >
   void trace( Args && ... args )
   {
      parse< Rule, Action, tracer >( std::forward< Args >( args ) ... );
   }

} // pegtl

#endif
<commit_msg>Pass result from parse() to trace()<commit_after>// Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#ifndef PEGTL_TRACE_HH
#define PEGTL_TRACE_HH

#include <iostream>

#include "parse.hh"
#include "normal.hh"
#include "nothing.hh"
#include "position_info.hh"

#include "internal/demangle.hh"

namespace pegtl
{
   template< typename Rule >
   struct tracer
         : normal< Rule >
   {
      template< typename Input, typename ... States >
      static void start( const Input & in, States && ... )
      {
         std::cerr << position_info( in ) << "  start  " << internal::demangle< Rule >() << std::endl;
      }

      template< typename Input, typename ... States >
      static void success( const Input & in, States && ... )
      {
         std::cerr << position_info( in ) << " success " << internal::demangle< Rule >() << std::endl;
      }

      template< typename Input, typename ... States >
      static void failure( const Input & in, States && ... )
      {
         std::cerr << position_info( in ) << " failure " << internal::demangle< Rule >() << std::endl;
      }
   };

   template< typename Rule, template< typename ... > class Action = nothing, typename ... Args >
   bool trace( Args && ... args )
   {
      return parse< Rule, Action, tracer >( std::forward< Args >( args ) ... );
   }

} // pegtl

#endif
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright (C) 2016 Felix Rohrbach <kde@fxrh.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include "mediathumbnailjob.h"

using namespace Quotient;

QUrl MediaThumbnailJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri,
                                       QSize requestedSize)
{
    return makeRequestUrl(std::move(baseUrl), mxcUri.authority(),
                          mxcUri.path().mid(1), requestedSize.width(),
                          requestedSize.height());
}

MediaThumbnailJob::MediaThumbnailJob(const QString& serverName,
                                     const QString& mediaId, QSize requestedSize)
    : GetContentThumbnailJob(serverName, mediaId, requestedSize.width(),
                             requestedSize.height())
{}

MediaThumbnailJob::MediaThumbnailJob(const QUrl& mxcUri, QSize requestedSize)
    : MediaThumbnailJob(mxcUri.authority(),
                        mxcUri.path().mid(1), // sans leading '/'
                        requestedSize)
{}

QImage MediaThumbnailJob::thumbnail() const { return _thumbnail; }

QImage MediaThumbnailJob::scaledThumbnail(QSize toSize) const
{
    return _thumbnail.scaled(toSize, Qt::KeepAspectRatio,
                             Qt::SmoothTransformation);
}

BaseJob::Status MediaThumbnailJob::parseReply(QNetworkReply* reply)
{
    auto result = GetContentThumbnailJob::parseReply(reply);
    if (!result.good())
        return result;

    if (_thumbnail.loadFromData(data()->readAll()))
        return Success;

    return { IncorrectResponseError,
             QStringLiteral("Could not read image data") };
}
<commit_msg>MediaThumbnailJob: be specific about the transform<commit_after>/******************************************************************************
 * Copyright (C) 2016 Felix Rohrbach <kde@fxrh.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include "mediathumbnailjob.h"

using namespace Quotient;

QUrl MediaThumbnailJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri,
                                       QSize requestedSize)
{
    return makeRequestUrl(std::move(baseUrl), mxcUri.authority(),
                          mxcUri.path().mid(1), requestedSize.width(),
                          requestedSize.height());
}

MediaThumbnailJob::MediaThumbnailJob(const QString& serverName,
                                     const QString& mediaId, QSize requestedSize)
    : GetContentThumbnailJob(serverName, mediaId, requestedSize.width(),
                             requestedSize.height(), "scale")
{}

MediaThumbnailJob::MediaThumbnailJob(const QUrl& mxcUri, QSize requestedSize)
    : MediaThumbnailJob(mxcUri.authority(),
                        mxcUri.path().mid(1), // sans leading '/'
                        requestedSize)
{}

QImage MediaThumbnailJob::thumbnail() const { return _thumbnail; }

QImage MediaThumbnailJob::scaledThumbnail(QSize toSize) const
{
    return _thumbnail.scaled(toSize, Qt::KeepAspectRatio,
                             Qt::SmoothTransformation);
}

BaseJob::Status MediaThumbnailJob::parseReply(QNetworkReply* reply)
{
    auto result = GetContentThumbnailJob::parseReply(reply);
    if (!result.good())
        return result;

    if (_thumbnail.loadFromData(data()->readAll()))
        return Success;

    return { IncorrectResponseError,
             QStringLiteral("Could not read image data") };
}
<|endoftext|>