<commit_before>//===-- ELFTargetAsmInfo.cpp - ELF asm properties ---------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take in general on ELF-based targets
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"

using namespace llvm;

ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
  : TargetAsmInfo(TM) {

  BSSSection_  = getUnnamedSection("\t.bss",
                                   SectionFlags::Writeable | SectionFlags::BSS);
  ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None);
  TLSDataSection = getNamedSection("\t.tdata",
                                   SectionFlags::Writeable | SectionFlags::TLS);
  TLSBSSSection = getNamedSection("\t.tbss",
                SectionFlags::Writeable | SectionFlags::TLS | SectionFlags::BSS);

  DataRelSection = getNamedSection("\t.data.rel", SectionFlags::Writeable);
  DataRelLocalSection = getNamedSection("\t.data.rel.local",
                                        SectionFlags::Writeable);
  DataRelROSection = getNamedSection("\t.data.rel.ro",
                                     SectionFlags::Writeable);
  DataRelROLocalSection = getNamedSection("\t.data.rel.ro.local",
                                          SectionFlags::Writeable);
}

SectionKind::Kind
ELFTargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
  SectionKind::Kind Kind = TargetAsmInfo::SectionKindForGlobal(GV);

  if (Kind != SectionKind::Data)
    return Kind;

  // Decide, whether we need data.rel stuff
  const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
  if (GVar->hasInitializer() && TM.getRelocationModel() != Reloc::Static) {
    Constant *C = GVar->getInitializer();
    bool isConstant = GVar->isConstant();

    // By default - all relocations in PIC mode would force symbol to be
    // placed in r/w section.
    switch (C->getRelocationInfo()) {
    default: break;
    case 1:
      return isConstant ? SectionKind::DataRelROLocal :
                          SectionKind::DataRelLocal;
    case 2:
      return isConstant ? SectionKind::DataRelRO : SectionKind::DataRel;
    }
  }

  return Kind;
}

const Section*
ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
  SectionKind::Kind Kind = SectionKindForGlobal(GV);

  if (const Function *F = dyn_cast<Function>(GV)) {
    switch (F->getLinkage()) {
     default: llvm_unreachable("Unknown linkage type!");
     case Function::PrivateLinkage:
     case Function::LinkerPrivateLinkage:
     case Function::InternalLinkage:
     case Function::DLLExportLinkage:
     case Function::ExternalLinkage:
      return TextSection;
     case Function::WeakAnyLinkage:
     case Function::WeakODRLinkage:
     case Function::LinkOnceAnyLinkage:
     case Function::LinkOnceODRLinkage:
      std::string Name = UniqueSectionForGlobal(GV, Kind);
      unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
      return getNamedSection(Name.c_str(), Flags);
    }
  } else if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
    if (GVar->isWeakForLinker()) {
      std::string Name = UniqueSectionForGlobal(GVar, Kind);
      unsigned Flags = SectionFlagsForGlobal(GVar, Name.c_str());
      return getNamedSection(Name.c_str(), Flags);
    } else {
      switch (Kind) {
      case SectionKind::Data:
      case SectionKind::SmallData:
        return DataSection;
      case SectionKind::DataRel:
        return DataRelSection;
      case SectionKind::DataRelLocal:
        return DataRelLocalSection;
      case SectionKind::DataRelRO:
        return DataRelROSection;
      case SectionKind::DataRelROLocal:
        return DataRelROLocalSection;
      case SectionKind::BSS:
      case SectionKind::SmallBSS:
        // ELF targets usually have BSS sections
        return getBSSSection_();
      case SectionKind::ROData:
      case SectionKind::SmallROData:
        return getReadOnlySection();
      case SectionKind::RODataMergeStr:
        return MergeableStringSection(GVar);
      case SectionKind::RODataMergeConst:
        return MergeableConstSection(GVar->getInitializer()->getType());
      case SectionKind::ThreadData:
        // ELF targets usually support TLS stuff
        return TLSDataSection;
      case SectionKind::ThreadBSS:
        return TLSBSSSection;
      default:
        llvm_unreachable("Unsuported section kind for global");
      }
    }
  } else
    llvm_unreachable("Unsupported global");

  return NULL;
}

/// getSectionForMergableConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const Section *
ELFTargetAsmInfo::getSectionForMergableConstant(uint64_t Size,
                                                unsigned ReloInfo) const {
  // FIXME: IF this global requires a relocation, can we really put it in
  // rodata???  This should check ReloInfo like darwin.

  const char *SecName = 0;
  switch (Size) {
  default: break;
  case 4:  SecName = ".rodata.cst4"; break;
  case 8:  SecName = ".rodata.cst8"; break;
  case 16: SecName = ".rodata.cst16"; break;
  }

  if (SecName)
    return getNamedSection(SecName,
                           SectionFlags::setEntitySize(SectionFlags::Mergeable|
                                                       SectionFlags::Small,
                                                       Size));

  return getReadOnlySection();  // .rodata
}

const Section*
ELFTargetAsmInfo::MergeableConstSection(const Type *Ty) const {
  const TargetData *TD = TM.getTargetData();
  return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0);
}

const Section*
ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
  const TargetData *TD = TM.getTargetData();
  Constant *C = cast<GlobalVariable>(GV)->getInitializer();
  const Type *Ty = cast<ArrayType>(C->getType())->getElementType();

  unsigned Size = TD->getTypeAllocSize(Ty);
  if (Size <= 16) {
    assert(getCStringSection() && "Should have string section prefix");

    // We also need alignment here
    unsigned Align = TD->getPrefTypeAlignment(Ty);
    if (Align < Size)
      Align = Size;

    std::string Name = getCStringSection() + utostr(Size) + '.' + utostr(Align);
    unsigned Flags = SectionFlags::setEntitySize(SectionFlags::Mergeable |
                                                 SectionFlags::Strings,
                                                 Size);
    return getNamedSection(Name.c_str(), Flags);
  }

  return getReadOnlySection();
}

std::string ELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
  std::string Flags = ",\"";

  if (!(flags & SectionFlags::Debug))
    Flags += 'a';
  if (flags & SectionFlags::Code)
    Flags += 'x';
  if (flags & SectionFlags::Writeable)
    Flags += 'w';
  if (flags & SectionFlags::Mergeable)
    Flags += 'M';
  if (flags & SectionFlags::Strings)
    Flags += 'S';
  if (flags & SectionFlags::TLS)
    Flags += 'T';
  if (flags & SectionFlags::Small)
    Flags += 's';

  Flags += "\",";

  // If comment string is '@', e.g. as on ARM - use '%' instead
  if (strcmp(CommentString, "@") == 0)
    Flags += '%';
  else
    Flags += '@';

  // FIXME: There can be exceptions here
  if (flags & SectionFlags::BSS)
    Flags += "nobits";
  else
    Flags += "progbits";

  if (unsigned entitySize = SectionFlags::getEntitySize(flags))
    Flags += "," + utostr(entitySize);

  return Flags;
}
<commit_msg>don't set the small flag yet.<commit_after>//===-- ELFTargetAsmInfo.cpp - ELF asm properties ---------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take in general on ELF-based targets
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"

using namespace llvm;

ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
  : TargetAsmInfo(TM) {

  BSSSection_  = getUnnamedSection("\t.bss",
                                   SectionFlags::Writeable | SectionFlags::BSS);
  ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None);
  TLSDataSection = getNamedSection("\t.tdata",
                                   SectionFlags::Writeable | SectionFlags::TLS);
  TLSBSSSection = getNamedSection("\t.tbss",
                SectionFlags::Writeable | SectionFlags::TLS | SectionFlags::BSS);

  DataRelSection = getNamedSection("\t.data.rel", SectionFlags::Writeable);
  DataRelLocalSection = getNamedSection("\t.data.rel.local",
                                        SectionFlags::Writeable);
  DataRelROSection = getNamedSection("\t.data.rel.ro",
                                     SectionFlags::Writeable);
  DataRelROLocalSection = getNamedSection("\t.data.rel.ro.local",
                                          SectionFlags::Writeable);
}

SectionKind::Kind
ELFTargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
  SectionKind::Kind Kind = TargetAsmInfo::SectionKindForGlobal(GV);

  if (Kind != SectionKind::Data)
    return Kind;

  // Decide, whether we need data.rel stuff
  const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
  if (GVar->hasInitializer() && TM.getRelocationModel() != Reloc::Static) {
    Constant *C = GVar->getInitializer();
    bool isConstant = GVar->isConstant();

    // By default - all relocations in PIC mode would force symbol to be
    // placed in r/w section.
    switch (C->getRelocationInfo()) {
    default: break;
    case 1:
      return isConstant ? SectionKind::DataRelROLocal :
                          SectionKind::DataRelLocal;
    case 2:
      return isConstant ? SectionKind::DataRelRO : SectionKind::DataRel;
    }
  }

  return Kind;
}

const Section*
ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
  SectionKind::Kind Kind = SectionKindForGlobal(GV);

  if (const Function *F = dyn_cast<Function>(GV)) {
    switch (F->getLinkage()) {
     default: llvm_unreachable("Unknown linkage type!");
     case Function::PrivateLinkage:
     case Function::LinkerPrivateLinkage:
     case Function::InternalLinkage:
     case Function::DLLExportLinkage:
     case Function::ExternalLinkage:
      return TextSection;
     case Function::WeakAnyLinkage:
     case Function::WeakODRLinkage:
     case Function::LinkOnceAnyLinkage:
     case Function::LinkOnceODRLinkage:
      std::string Name = UniqueSectionForGlobal(GV, Kind);
      unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
      return getNamedSection(Name.c_str(), Flags);
    }
  } else if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
    if (GVar->isWeakForLinker()) {
      std::string Name = UniqueSectionForGlobal(GVar, Kind);
      unsigned Flags = SectionFlagsForGlobal(GVar, Name.c_str());
      return getNamedSection(Name.c_str(), Flags);
    } else {
      switch (Kind) {
      case SectionKind::Data:
      case SectionKind::SmallData:
        return DataSection;
      case SectionKind::DataRel:
        return DataRelSection;
      case SectionKind::DataRelLocal:
        return DataRelLocalSection;
      case SectionKind::DataRelRO:
        return DataRelROSection;
      case SectionKind::DataRelROLocal:
        return DataRelROLocalSection;
      case SectionKind::BSS:
      case SectionKind::SmallBSS:
        // ELF targets usually have BSS sections
        return getBSSSection_();
      case SectionKind::ROData:
      case SectionKind::SmallROData:
        return getReadOnlySection();
      case SectionKind::RODataMergeStr:
        return MergeableStringSection(GVar);
      case SectionKind::RODataMergeConst:
        return MergeableConstSection(GVar->getInitializer()->getType());
      case SectionKind::ThreadData:
        // ELF targets usually support TLS stuff
        return TLSDataSection;
      case SectionKind::ThreadBSS:
        return TLSBSSSection;
      default:
        llvm_unreachable("Unsuported section kind for global");
      }
    }
  } else
    llvm_unreachable("Unsupported global");

  return NULL;
}

/// getSectionForMergableConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const Section *
ELFTargetAsmInfo::getSectionForMergableConstant(uint64_t Size,
                                                unsigned ReloInfo) const {
  // FIXME: IF this global requires a relocation, can we really put it in
  // rodata???  This should check ReloInfo like darwin.

  const char *SecName = 0;
  switch (Size) {
  default: break;
  case 4:  SecName = ".rodata.cst4"; break;
  case 8:  SecName = ".rodata.cst8"; break;
  case 16: SecName = ".rodata.cst16"; break;
  }

  if (SecName)
    return getNamedSection(SecName,
                           SectionFlags::setEntitySize(SectionFlags::Mergeable,
                                                       Size));

  return getReadOnlySection();  // .rodata
}

const Section*
ELFTargetAsmInfo::MergeableConstSection(const Type *Ty) const {
  const TargetData *TD = TM.getTargetData();
  return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0);
}

const Section*
ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
  const TargetData *TD = TM.getTargetData();
  Constant *C = cast<GlobalVariable>(GV)->getInitializer();
  const Type *Ty = cast<ArrayType>(C->getType())->getElementType();

  unsigned Size = TD->getTypeAllocSize(Ty);
  if (Size <= 16) {
    assert(getCStringSection() && "Should have string section prefix");

    // We also need alignment here
    unsigned Align = TD->getPrefTypeAlignment(Ty);
    if (Align < Size)
      Align = Size;

    std::string Name = getCStringSection() + utostr(Size) + '.' + utostr(Align);
    unsigned Flags = SectionFlags::setEntitySize(SectionFlags::Mergeable |
                                                 SectionFlags::Strings,
                                                 Size);
    return getNamedSection(Name.c_str(), Flags);
  }

  return getReadOnlySection();
}

std::string ELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
  std::string Flags = ",\"";

  if (!(flags & SectionFlags::Debug))
    Flags += 'a';
  if (flags & SectionFlags::Code)
    Flags += 'x';
  if (flags & SectionFlags::Writeable)
    Flags += 'w';
  if (flags & SectionFlags::Mergeable)
    Flags += 'M';
  if (flags & SectionFlags::Strings)
    Flags += 'S';
  if (flags & SectionFlags::TLS)
    Flags += 'T';
  if (flags & SectionFlags::Small)
    Flags += 's';

  Flags += "\",";

  // If comment string is '@', e.g. as on ARM - use '%' instead
  if (strcmp(CommentString, "@") == 0)
    Flags += '%';
  else
    Flags += '@';

  // FIXME: There can be exceptions here
  if (flags & SectionFlags::BSS)
    Flags += "nobits";
  else
    Flags += "progbits";

  if (unsigned entitySize = SectionFlags::getEntitySize(flags))
    Flags += "," + utostr(entitySize);

  return Flags;
}
<|endoftext|>


<commit_before>//===- X86InstrInfo.cpp - X86 Instruction Information -----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the X86 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//

#include "X86InstrInfo.h"
#include "X86.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "X86GenInstrInfo.inc"
using namespace llvm;

X86InstrInfo::X86InstrInfo()
  : TargetInstrInfo(X86Insts, sizeof(X86Insts)/sizeof(X86Insts[0])) {
}

bool X86InstrInfo::isMoveInstr(const MachineInstr& MI,
                               unsigned& sourceReg,
                               unsigned& destReg) const {
  MachineOpCode oc = MI.getOpcode();
  if (oc == X86::MOV8rr || oc == X86::MOV16rr || oc == X86::MOV32rr ||
      oc == X86::FpMOV) {
      assert(MI.getNumOperands() == 2 &&
             MI.getOperand(0).isRegister() &&
             MI.getOperand(1).isRegister() &&
             "invalid register-register move instruction");
      sourceReg = MI.getOperand(1).getReg();
      destReg = MI.getOperand(0).getReg();
      return true;
  }
  return false;
}

void X86InstrInfo::insertGoto(MachineBasicBlock& MBB,
                              MachineBasicBlock& TMBB) const {
  BuildMI(MBB, MBB.end(), X86::JMP, 1).addMBB(&TMBB);
}

MachineBasicBlock::iterator
X86InstrInfo::reverseBranchCondition(MachineBasicBlock::iterator MI) const {
  unsigned Opcode = MI->getOpcode();
  assert(isBranch(Opcode) && "MachineInstr must be a branch");
  unsigned ROpcode;
  switch (Opcode) {
  case X86::JB:  ROpcode = X86::JAE;
  case X86::JAE: ROpcode = X86::JB;
  case X86::JE:  ROpcode = X86::JNE;
  case X86::JNE: ROpcode = X86::JE;
  case X86::JBE: ROpcode = X86::JA;
  case X86::JA:  ROpcode = X86::JBE;
  case X86::JS:  ROpcode = X86::JNS;
  case X86::JNS: ROpcode = X86::JS;
  case X86::JL:  ROpcode = X86::JGE;
  case X86::JGE: ROpcode = X86::JL;
  case X86::JLE: ROpcode = X86::JG;
  case X86::JG:  ROpcode = X86::JLE;
  default:
    assert(0 && "Cannot reverse unconditional branches!");
  }
  MachineBasicBlock* MBB = MI->getParent();
  MachineBasicBlock* TMBB = MI->getOperand(0).getMachineBasicBlock();
  MachineInstrBuilder IB = BuildMI(*MBB, MBB->erase(MI), ROpcode, 1);
  IB.addMBB(TMBB);
  return IB;
}
<commit_msg>Simplify code a bit.<commit_after>//===- X86InstrInfo.cpp - X86 Instruction Information -----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the X86 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//

#include "X86InstrInfo.h"
#include "X86.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "X86GenInstrInfo.inc"
using namespace llvm;

X86InstrInfo::X86InstrInfo()
  : TargetInstrInfo(X86Insts, sizeof(X86Insts)/sizeof(X86Insts[0])) {
}

bool X86InstrInfo::isMoveInstr(const MachineInstr& MI,
                               unsigned& sourceReg,
                               unsigned& destReg) const {
  MachineOpCode oc = MI.getOpcode();
  if (oc == X86::MOV8rr || oc == X86::MOV16rr || oc == X86::MOV32rr ||
      oc == X86::FpMOV) {
      assert(MI.getNumOperands() == 2 &&
             MI.getOperand(0).isRegister() &&
             MI.getOperand(1).isRegister() &&
             "invalid register-register move instruction");
      sourceReg = MI.getOperand(1).getReg();
      destReg = MI.getOperand(0).getReg();
      return true;
  }
  return false;
}

void X86InstrInfo::insertGoto(MachineBasicBlock& MBB,
                              MachineBasicBlock& TMBB) const {
  BuildMI(MBB, MBB.end(), X86::JMP, 1).addMBB(&TMBB);
}

MachineBasicBlock::iterator
X86InstrInfo::reverseBranchCondition(MachineBasicBlock::iterator MI) const {
  unsigned Opcode = MI->getOpcode();
  assert(isBranch(Opcode) && "MachineInstr must be a branch");
  unsigned ROpcode;
  switch (Opcode) {
  case X86::JB:  ROpcode = X86::JAE;
  case X86::JAE: ROpcode = X86::JB;
  case X86::JE:  ROpcode = X86::JNE;
  case X86::JNE: ROpcode = X86::JE;
  case X86::JBE: ROpcode = X86::JA;
  case X86::JA:  ROpcode = X86::JBE;
  case X86::JS:  ROpcode = X86::JNS;
  case X86::JNS: ROpcode = X86::JS;
  case X86::JL:  ROpcode = X86::JGE;
  case X86::JGE: ROpcode = X86::JL;
  case X86::JLE: ROpcode = X86::JG;
  case X86::JG:  ROpcode = X86::JLE;
  default:
    assert(0 && "Cannot reverse unconditional branches!");
  }
  MachineBasicBlock* MBB = MI->getParent();
  MachineBasicBlock* TMBB = MI->getOperand(0).getMachineBasicBlock();
  return BuildMI(*MBB, MBB->erase(MI), ROpcode, 1).addMBB(TMBB);
}
<|endoftext|>


<commit_before>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/**
    Example for Mr G. Royle :
    Compute the integer characteristic polynomial of symetric matrices with
    0,1 coefficients
*/

#include <iostream>

#include "linbox/blackbox/zero-one.h"
#include "linbox/field/PID-integer.h"
#include "linbox/solutions/charpoly.h"
#include "linbox/ring/givaro-polynomial.h"
#include "linbox/solutions/methods.h"

using namespace std;
using namespace LinBox;

template <class Field, class Polynomial>
void printPolynomial(const Field& F, const Polynomial& P){
	int n= P.size()-1;
	for (int i=0;i<n;++i)
		cout<<P[i]<<" ";
	cout<<endl;
	if (n==1){
		cout<<"X";
		if ( P[0] != 0)
			F.write(cout<<((P[0]>0)?"+":""),P[0]);
	}
	else{
		cout<<"X^"<<n;
		for ( int i=n-1; i>1; --i)
			if (!F.isZero(P[i]))
				F.write(cout<<((P[i]>0)?"+":""),P[i])<<"*X^"<<i;
		if ( P[1] != 0)
			F.write(cout<<((P[1]>0)?"+":""),P[1])<<"*X";
		if ( P[0] != 0)
			F.write(cout<<((P[0]>0)?"+":""),P[0]);
	}
}

typedef ZeroOne<PID_integer> Matrix;
typedef GivPolynomialRing<PID_integer,Dense> IntPolRing;

int main (int argc, char **argv)
{
	commentator.getMessageClass (BRIEF_REPORT).setMaxDepth (2);
	commentator.getMessageClass (BRIEF_REPORT).setMaxDetailLevel (Commentator::LEVEL_UNIMPORTANT);

	if (argc != 2) {
		cerr << "Usage: graph-charpoly <matrix-file-in-SMS-format>" <<endl;
		return -1;
	}

	ifstream input (argv[1]);
	if (!input) {
	  cerr << "Error opening matrix file " << argv[1] << endl;
	  return -1;
	}

	//UnparametricField<integer> ZZ;
	PID_integer ZZ;
	Matrix A;
	A.read (input);
	commentator.report(1, BRIEF_REPORT)<< "A is " << A.rowdim() << " by " << A.coldim() << endl;

	IntPolRing::Element c_A;

	charpoly (c_A, A, Method::Blackbox(Method::Wiedemann( Specifier::SYMMETRIC)));

	cout<< "Characteristic Polynomial is ";
	printPolynomial (ZZ, c_A);

	return 0;
}
<commit_msg>cstor with Field<commit_after>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/**
    Example for Mr G. Royle :
    Compute the integer characteristic polynomial of symetric matrices with
    0,1 coefficients
*/

#include <iostream>

#include "linbox/blackbox/zero-one.h"
#include "linbox/field/PID-integer.h"
#include "linbox/solutions/charpoly.h"
#include "linbox/ring/givaro-polynomial.h"
#include "linbox/solutions/methods.h"

using namespace std;
using namespace LinBox;

template <class Field, class Polynomial>
void printPolynomial(const Field& F, const Polynomial& P){
	int n= P.size()-1;
	for (int i=0;i<n;++i)
		cout<<P[i]<<" ";
	cout<<endl;
	if (n==1){
		cout<<"X";
		if ( P[0] != 0)
			F.write(cout<<((P[0]>0)?"+":""),P[0]);
	}
	else{
		cout<<"X^"<<n;
		for ( int i=n-1; i>1; --i)
			if (!F.isZero(P[i]))
				F.write(cout<<((P[i]>0)?"+":""),P[i])<<"*X^"<<i;
		if ( P[1] != 0)
			F.write(cout<<((P[1]>0)?"+":""),P[1])<<"*X";
		if ( P[0] != 0)
			F.write(cout<<((P[0]>0)?"+":""),P[0]);
	}
}

typedef ZeroOne<PID_integer> Matrix;
typedef GivPolynomialRing<PID_integer,Dense> IntPolRing;

int main (int argc, char **argv)
{
	commentator.getMessageClass (BRIEF_REPORT).setMaxDepth (2);
	commentator.getMessageClass (BRIEF_REPORT).setMaxDetailLevel (Commentator::LEVEL_UNIMPORTANT);

	if (argc != 2) {
		cerr << "Usage: graph-charpoly <matrix-file-in-SMS-format>" <<endl;
		return -1;
	}

	ifstream input (argv[1]);
	if (!input) {
	  cerr << "Error opening matrix file " << argv[1] << endl;
	  return -1;
	}

	//UnparametricField<integer> ZZ;
	PID_integer ZZ;
	Matrix A(ZZ);
	A.read (input);
	commentator.report(1, BRIEF_REPORT)<< "A is " << A.rowdim() << " by " << A.coldim() << endl;

	IntPolRing::Element c_A;

	charpoly (c_A, A, Method::Blackbox(Method::Wiedemann( Specifier::SYMMETRIC)));

	cout<< "Characteristic Polynomial is ";
	printPolynomial (ZZ, c_A);

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>

#include "vm.hpp"

#include "exception.hpp"
#include "exception_point.hpp"
#include "arguments.hpp"
#include "dispatch.hpp"
#include "native_libraries.hpp"
#include "primitives.hpp"
#include "call_frame.hpp"

#include "builtin/array.hpp"
#include "builtin/exception.hpp"
#include "builtin/nativemethod.hpp"
#include "builtin/string.hpp"
#include "builtin/system.hpp"
#include "builtin/tuple.hpp"
#include "builtin/capi_handle.hpp"

#include "instruments/profiler.hpp"

#include "capi/capi.hpp"
#include "capi/handle.hpp"

namespace rubinius {
  /** Thread-local NativeMethodEnvironment instance. */
  thread::ThreadData<NativeMethodEnvironment*> native_method_environment;

/* Class methods */

  NativeMethodEnvironment* NativeMethodEnvironment::get() {
    return native_method_environment.get();
  }

  NativeMethodFrame::~NativeMethodFrame() {
    flush_cached_data(true);
    for(capi::HandleList::iterator i = handles_.begin();
        i != handles_.end();
        i++) {
      capi::Handle* handle = *i;
      handle->deref();
    }
  }

  VALUE NativeMethodFrame::get_handle(STATE, Object* obj) {
    capi::Handle* handle;

    Object* existing = obj->get_table_ivar(state, state->symbol("capi_handle"));

    if(CApiHandle* wrapper = try_as<CApiHandle>(existing)) {
      handle = wrapper->handle;
    } else {
      handle = new capi::Handle(state, obj);
      state->shared.global_handles()->add(handle);
      CApiHandle* wrapper = CApiHandle::create(state, handle);
      obj->set_table_ivar(state, state->symbol("capi_handle"), wrapper);
    }

    handle->ref();

    handles_.push_back(handle);
    return handle->as_value();
  }

  Object* NativeMethodFrame::get_object(VALUE val) {
    return capi::Handle::from(val)->object();
  }

  CApiStructs& NativeMethodFrame::strings() {
    if(!strings_) strings_ = new CApiStructs;
    return *strings_;
  }

  CApiStructs& NativeMethodFrame::arrays() {
    if(!arrays_) arrays_ = new CApiStructs;
    return *arrays_;
  }

  CApiStructs& NativeMethodFrame::data() {
    if(!data_) data_ = new CApiStructs;
    return *data_;
  }

  void NativeMethodFrame::flush_cached_data(bool release_memory) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    for(capi::HandleList::iterator i = handles_.begin();
        i != handles_.end();
        i++) {
      capi::Handle* handle = *i;
      if(handle->is_rarray()) {
        capi::capi_get_array(env, handle->as_value());
      } else if(handle->is_rstring()) {
        capi::capi_get_string(env, handle->as_value());
      } else if(handle->is_rdata()) {
        capi::capi_rdata_flush_handle(env, handle);
      }

      if(release_memory) handle->free_data();
    }
  }

  void NativeMethodFrame::update_cached_data() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    for(capi::HandleList::iterator i = handles_.begin();
        i != handles_.end();
        i++) {
      capi::Handle* handle = *i;
      if(handle->is_rarray()) {
        capi::capi_update_array(env, handle->as_value());
      } else if(handle->is_rstring()) {
        capi::capi_update_string(env, handle->as_value());
      }
    }
  }

  VALUE NativeMethodEnvironment::get_handle(Object* obj) {
    if(obj->reference_p()) {
      return current_native_frame_->get_handle(state_, obj);
    } else if(obj->fixnum_p() || obj->symbol_p()) {
      return reinterpret_cast<VALUE>(obj);
    } else if(obj->nil_p()) {
      return cCApiHandleQnil;
    } else if(obj->false_p()) {
      return cCApiHandleQfalse;
    } else if(obj->true_p()) {
      return cCApiHandleQtrue;
    } else if(obj->undef_p()) {
      return cCApiHandleQundef;
    }

    capi::capi_raise_runtime_error("NativeMethod handle requested for unknown object type");
    return 0; // keep compiler happy
  }

  Object* NativeMethodEnvironment::get_object(VALUE val) {
    if(CAPI_REFERENCE_P(val)) {
      return capi::Handle::from(val)->object();
      /*
      if(CAPI_GLOBAL_HANDLE_P(handle)) {
        Handles& global_handles = state_->shared.global_handles();
        size_t index = CAPI_STRIP_GLOBAL_TAG(handle);
        if(unlikely(index >= global_handles.size())) {
          capi_raise_runtime_error("requested Object for invalid NativeMethod global handle");
        }

        RootHandle* root = global_handles[index];

        if(unlikely(!root)) {
          capi_raise_runtime_error("Attempted to use deleted NativeMethod global handle");
        }

        Object* obj = root->get();
        if(unlikely(!obj)) {
          capi_raise_runtime_error("NativeMethod global handle refers to NULL object");
        }
        return obj;
      } else {
        return current_native_frame_->get_object(handle);
      }
      */
    } else if(FIXNUM_P(val) || SYMBOL_P(val)) {
      return reinterpret_cast<Object*>(val);
    } else if(CAPI_FALSE_P(val)) {
      return Qfalse;
    } else if(CAPI_TRUE_P(val)) {
      return Qtrue;
    } else if(CAPI_NIL_P(val)) {
      return Qnil;
    } else if(CAPI_UNDEF_P(val)) {
      return Qundef;
    }

    capi::capi_raise_runtime_error("requested Object for unknown NativeMethod handle type");
    return Qnil; // keep compiler happy
  }

  void NativeMethodEnvironment::delete_global(VALUE val) {
    abort();
  }

  Object* NativeMethodEnvironment::block() {
    return current_call_frame_->top_scope->block();
  }

  capi::HandleList& NativeMethodEnvironment::handles() {
    return current_native_frame_->handles();
  }

  CApiStructs& NativeMethodEnvironment::strings() {
    return current_native_frame_->strings();
  }

  CApiStructs& NativeMethodEnvironment::arrays() {
    return current_native_frame_->arrays();
  }

  CApiStructs& NativeMethodEnvironment::data() {
    return current_native_frame_->data();
  }

  void NativeMethodEnvironment::flush_cached_data(bool release_memory) {
    current_native_frame_->flush_cached_data(release_memory);
  }

  void NativeMethodEnvironment::update_cached_data() {
    current_native_frame_->update_cached_data();
  }

  void NativeMethod::init(STATE) {
    state->globals.nmethod.set(state->new_class("NativeMethod", G(executable), G(rubinius)));
    state->globals.nmethod.get()->set_object_type(state, NativeMethodType);

    init_thread(state);
  }

  void NativeMethod::init_thread(STATE) {
    NativeMethodEnvironment* env = new NativeMethodEnvironment;
    env->set_state(state);
    native_method_environment.set(env);
  }

  NativeMethod* NativeMethod::allocate(STATE) {
    return create<GenericFunctor>(state);
  }

  Object* NativeMethod::executor_implementation(STATE,
      CallFrame* call_frame, Dispatch& msg, Arguments& args) {
    NativeMethod* nm = as<NativeMethod>(msg.method);

    int arity = nm->arity()->to_int();
    if(arity >= 0 && (size_t)arity != args.total()) {
      Exception* exc = Exception::make_argument_error(
          state, arity, args.total(), msg.name);
      exc->locations(state, System::vm_backtrace(state, Fixnum::from(1), call_frame));
      state->thread_state()->raise_exception(exc);

      return NULL;
    }

    NativeMethodEnvironment* env = native_method_environment.get();
    NativeMethodFrame nmf(env->current_native_frame());

    env->set_current_call_frame(call_frame);
    env->set_current_native_frame(&nmf);

    Object* ret;
    ExceptionPoint ep(env);

    PLACE_EXCEPTION_POINT(ep);

    if(unlikely(ep.jumped_to())) {
      ret = NULL;
    } else {
#ifdef RBX_PROFILER
      if(unlikely(state->shared.profiling())) {
        profiler::MethodEntry method(state, msg, args);
        ret = nm->call(state, env, args);
      } else {
        ret = nm->call(state, env, args);
      }
#else
      ret = nm->call(state, env, args);
#endif
    }

    env->set_current_native_frame(nmf.previous());
    ep.pop(env);

    return ret;
  }

  NativeMethod* NativeMethod::load_extension_entry_point(STATE, String* path, String* name) {
    void* func = NativeLibrary::find_symbol(state, name, path);

    NativeMethod* m = NativeMethod::create(state,
                                           path,
                                           state->globals.rubinius.get(),
                                           name->to_sym(state),
                                           reinterpret_cast<GenericFunctor>(func),
                                           Fixnum::from(INIT_FUNCTION)
                                          );
    return m;
  }

  /**
   *    Arity -3:   VALUE func(VALUE argument_array);
   *    Arity -2:   VALUE func(VALUE receiver, VALUE argument_array);
   *    Arity -1:   VALUE func(int argument_count, VALUE*, VALUE receiver);
   *    Otherwise:  VALUE func(VALUE receiver, VALUE arg1[, VALUE arg2, ...]);
   *
   *  There is also a special-case arity, INIT_FUNCTION, which corresponds
   *  to void (*)(void) and should never appear in user code.
   *
   *  @note   Currently supports functions with up to receiver + 5 (separate) arguments only!
   *          Anything beyond that should use one of the special arities instead.
   *
   *  @todo   Check for inefficiencies.
   */
  Object* NativeMethod::call(STATE, NativeMethodEnvironment* env, Arguments& args) {
    VALUE receiver = env->get_handle(args.recv());

    switch(arity()->to_int()) {
    case ARGS_IN_RUBY_ARRAY: {  /* Braces required to create objects in a switch */
      VALUE ary = env->get_handle(args.as_array(state));

      VALUE ret = functor_as<OneArgFunctor>()(ary);

      return env->get_object(ret);
    }

    case RECEIVER_PLUS_ARGS_IN_RUBY_ARRAY: {
      VALUE ary = env->get_handle(args.as_array(state));

      VALUE ret = functor_as<TwoArgFunctor>()(receiver, ary);

      return env->get_object(ret);
    }

    case ARG_COUNT_ARGS_IN_C_ARRAY_PLUS_RECEIVER: {
      VALUE* ary = new VALUE[args.total()];

      for (std::size_t i = 0; i < args.total(); ++i) {
        ary[i] = env->get_handle(args.get_argument(i));
      }

      VALUE ret = functor_as<ArgcFunctor>()(args.total(), ary, receiver);

      delete[] ary;

      return env->get_object(ret);
    }

      /*
       *  Normal arg counts
       *
       *  Yes, it is ugly as fuck. It is intended as an encouragement
       *  to get rid of the concept of a separate VALUE and Object.
       */

    case 0: {
      OneArgFunctor functor = functor_as<OneArgFunctor>();

      VALUE ret = functor(receiver);

      return env->get_object(ret);
    }

    case 1: {
      TwoArgFunctor functor = functor_as<TwoArgFunctor>();

      VALUE a1 = env->get_handle(args.get_argument(0));

      VALUE ret = functor(receiver, a1);

      return env->get_object(ret);
    }

    case 2: {
      ThreeArgFunctor functor = functor_as<ThreeArgFunctor>();

      VALUE a1 = env->get_handle(args.get_argument(0));
      VALUE a2 = env->get_handle(args.get_argument(1));

      VALUE ret = functor(receiver, a1, a2);

      return env->get_object(ret);
    }

    case 3: {
      FourArgFunctor functor = functor_as<FourArgFunctor>();
      VALUE a1 = env->get_handle(args.get_argument(0));
      VALUE a2 = env->get_handle(args.get_argument(1));
      VALUE a3 = env->get_handle(args.get_argument(2));

      VALUE ret = functor(receiver, a1, a2, a3);

      return env->get_object(ret);
    }

    case 4: {
      FiveArgFunctor functor = functor_as<FiveArgFunctor>();
      VALUE a1 = env->get_handle(args.get_argument(0));
      VALUE a2 = env->get_handle(args.get_argument(1));
      VALUE a3 = env->get_handle(args.get_argument(2));
      VALUE a4 = env->get_handle(args.get_argument(3));

      VALUE ret = functor(receiver, a1, a2, a3, a4);

      return env->get_object(ret);
    }

    case 5: {
      SixArgFunctor functor = functor_as<SixArgFunctor>();
      VALUE a1 = env->get_handle(args.get_argument(0));
      VALUE a2 = env->get_handle(args.get_argument(1));
      VALUE a3 = env->get_handle(args.get_argument(2));
      VALUE a4 = env->get_handle(args.get_argument(3));
      VALUE a5 = env->get_handle(args.get_argument(4));

      VALUE ret = functor(receiver, a1, a2, a3, a4, a5);

      return env->get_object(ret);
    }

      /* Extension entry point, should never occur for user code. */
    case INIT_FUNCTION: {
      InitFunctor functor = functor_as<InitFunctor>();

      functor();

      return Qnil;
    }

    default:
      capi::capi_raise_runtime_error("unrecognized arity for NativeMethod call");
      return Qnil;
    }
  }

}
<commit_msg>Fixed saving call_frame through native calls (pair Evan).<commit_after>#include <iostream>

#include "vm.hpp"

#include "exception.hpp"
#include "exception_point.hpp"
#include "arguments.hpp"
#include "dispatch.hpp"
#include "native_libraries.hpp"
#include "primitives.hpp"
#include "call_frame.hpp"

#include "builtin/array.hpp"
#include "builtin/exception.hpp"
#include "builtin/nativemethod.hpp"
#include "builtin/string.hpp"
#include "builtin/system.hpp"
#include "builtin/tuple.hpp"
#include "builtin/capi_handle.hpp"

#include "instruments/profiler.hpp"

#include "capi/capi.hpp"
#include "capi/handle.hpp"

namespace rubinius {
  /** Thread-local NativeMethodEnvironment instance. */
  thread::ThreadData<NativeMethodEnvironment*> native_method_environment;

/* Class methods */

  NativeMethodEnvironment* NativeMethodEnvironment::get() {
    return native_method_environment.get();
  }

  NativeMethodFrame::~NativeMethodFrame() {
    flush_cached_data(true);
    for(capi::HandleList::iterator i = handles_.begin();
        i != handles_.end();
        i++) {
      capi::Handle* handle = *i;
      handle->deref();
    }
  }

  VALUE NativeMethodFrame::get_handle(STATE, Object* obj) {
    capi::Handle* handle;

    Object* existing = obj->get_table_ivar(state, state->symbol("capi_handle"));

    if(CApiHandle* wrapper = try_as<CApiHandle>(existing)) {
      handle = wrapper->handle;
    } else {
      handle = new capi::Handle(state, obj);
      state->shared.global_handles()->add(handle);
      CApiHandle* wrapper = CApiHandle::create(state, handle);
      obj->set_table_ivar(state, state->symbol("capi_handle"), wrapper);
    }

    handle->ref();

    handles_.push_back(handle);
    return handle->as_value();
  }

  Object* NativeMethodFrame::get_object(VALUE val) {
    return capi::Handle::from(val)->object();
  }

  CApiStructs& NativeMethodFrame::strings() {
    if(!strings_) strings_ = new CApiStructs;
    return *strings_;
  }

  CApiStructs& NativeMethodFrame::arrays() {
    if(!arrays_) arrays_ = new CApiStructs;
    return *arrays_;
  }

  CApiStructs& NativeMethodFrame::data() {
    if(!data_) data_ = new CApiStructs;
    return *data_;
  }

  void NativeMethodFrame::flush_cached_data(bool release_memory) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    for(capi::HandleList::iterator i = handles_.begin();
        i != handles_.end();
        i++) {
      capi::Handle* handle = *i;
      if(handle->is_rarray()) {
        capi::capi_get_array(env, handle->as_value());
      } else if(handle->is_rstring()) {
        capi::capi_get_string(env, handle->as_value());
      } else if(handle->is_rdata()) {
        capi::capi_rdata_flush_handle(env, handle);
      }

      if(release_memory) handle->free_data();
    }
  }

  void NativeMethodFrame::update_cached_data() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    for(capi::HandleList::iterator i = handles_.begin();
        i != handles_.end();
        i++) {
      capi::Handle* handle = *i;
      if(handle->is_rarray()) {
        capi::capi_update_array(env, handle->as_value());
      } else if(handle->is_rstring()) {
        capi::capi_update_string(env, handle->as_value());
      }
    }
  }

  VALUE NativeMethodEnvironment::get_handle(Object* obj) {
    if(obj->reference_p()) {
      return current_native_frame_->get_handle(state_, obj);
    } else if(obj->fixnum_p() || obj->symbol_p()) {
      return reinterpret_cast<VALUE>(obj);
    } else if(obj->nil_p()) {
      return cCApiHandleQnil;
    } else if(obj->false_p()) {
      return cCApiHandleQfalse;
    } else if(obj->true_p()) {
      return cCApiHandleQtrue;
    } else if(obj->undef_p()) {
      return cCApiHandleQundef;
    }

    capi::capi_raise_runtime_error("NativeMethod handle requested for unknown object type");
    return 0; // keep compiler happy
  }

  Object* NativeMethodEnvironment::get_object(VALUE val) {
    if(CAPI_REFERENCE_P(val)) {
      return capi::Handle::from(val)->object();
      /*
      if(CAPI_GLOBAL_HANDLE_P(handle)) {
        Handles& global_handles = state_->shared.global_handles();
        size_t index = CAPI_STRIP_GLOBAL_TAG(handle);
        if(unlikely(index >= global_handles.size())) {
          capi_raise_runtime_error("requested Object for invalid NativeMethod global handle");
        }

        RootHandle* root = global_handles[index];

        if(unlikely(!root)) {
          capi_raise_runtime_error("Attempted to use deleted NativeMethod global handle");
        }

        Object* obj = root->get();
        if(unlikely(!obj)) {
          capi_raise_runtime_error("NativeMethod global handle refers to NULL object");
        }
        return obj;
      } else {
        return current_native_frame_->get_object(handle);
      }
      */
    } else if(FIXNUM_P(val) || SYMBOL_P(val)) {
      return reinterpret_cast<Object*>(val);
    } else if(CAPI_FALSE_P(val)) {
      return Qfalse;
    } else if(CAPI_TRUE_P(val)) {
      return Qtrue;
    } else if(CAPI_NIL_P(val)) {
      return Qnil;
    } else if(CAPI_UNDEF_P(val)) {
      return Qundef;
    }

    capi::capi_raise_runtime_error("requested Object for unknown NativeMethod handle type");
    return Qnil; // keep compiler happy
  }

  void NativeMethodEnvironment::delete_global(VALUE val) {
    abort();
  }

  Object* NativeMethodEnvironment::block() {
    return current_call_frame_->top_scope->block();
  }

  capi::HandleList& NativeMethodEnvironment::handles() {
    return current_native_frame_->handles();
  }

  CApiStructs& NativeMethodEnvironment::strings() {
    return current_native_frame_->strings();
  }

  CApiStructs& NativeMethodEnvironment::arrays() {
    return current_native_frame_->arrays();
  }

  CApiStructs& NativeMethodEnvironment::data() {
    return current_native_frame_->data();
  }

  void NativeMethodEnvironment::flush_cached_data(bool release_memory) {
    current_native_frame_->flush_cached_data(release_memory);
  }

  void NativeMethodEnvironment::update_cached_data() {
    current_native_frame_->update_cached_data();
  }

  void NativeMethod::init(STATE) {
    state->globals.nmethod.set(state->new_class("NativeMethod", G(executable), G(rubinius)));
    state->globals.nmethod.get()->set_object_type(state, NativeMethodType);

    init_thread(state);
  }

  void NativeMethod::init_thread(STATE) {
    NativeMethodEnvironment* env = new NativeMethodEnvironment;
    env->set_state(state);
    native_method_environment.set(env);
  }

  NativeMethod* NativeMethod::allocate(STATE) {
    return create<GenericFunctor>(state);
  }

  Object* NativeMethod::executor_implementation(STATE,
      CallFrame* call_frame, Dispatch& msg, Arguments& args) {
    NativeMethod* nm = as<NativeMethod>(msg.method);

    int arity = nm->arity()->to_int();
    if(arity >= 0 && (size_t)arity != args.total()) {
      Exception* exc = Exception::make_argument_error(
          state, arity, args.total(), msg.name);
      exc->locations(state, System::vm_backtrace(state, Fixnum::from(1), call_frame));
      state->thread_state()->raise_exception(exc);

      return NULL;
    }

    NativeMethodEnvironment* env = native_method_environment.get();
    NativeMethodFrame nmf(env->current_native_frame());

    CallFrame* saved_frame = env->current_call_frame();
    env->set_current_call_frame(call_frame);
    env->set_current_native_frame(&nmf);

    Object* ret;
    ExceptionPoint ep(env);

    PLACE_EXCEPTION_POINT(ep);

    if(unlikely(ep.jumped_to())) {
      ret = NULL;
    } else {
#ifdef RBX_PROFILER
      if(unlikely(state->shared.profiling())) {
        profiler::MethodEntry method(state, msg, args);
        ret = nm->call(state, env, args);
      } else {
        ret = nm->call(state, env, args);
      }
#else
      ret = nm->call(state, env, args);
#endif
    }

    env->set_current_call_frame(saved_frame);
    env->set_current_native_frame(nmf.previous());
    ep.pop(env);

    return ret;
  }

  NativeMethod* NativeMethod::load_extension_entry_point(STATE, String* path, String* name) {
    void* func = NativeLibrary::find_symbol(state, name, path);

    NativeMethod* m = NativeMethod::create(state,
                                           path,
                                           state->globals.rubinius.get(),
                                           name->to_sym(state),
                                           reinterpret_cast<GenericFunctor>(func),
                                           Fixnum::from(INIT_FUNCTION)
                                          );
    return m;
  }

  /**
   *    Arity -3:   VALUE func(VALUE argument_array);
   *    Arity -2:   VALUE func(VALUE receiver, VALUE argument_array);
   *    Arity -1:   VALUE func(int argument_count, VALUE*, VALUE receiver);
   *    Otherwise:  VALUE func(VALUE receiver, VALUE arg1[, VALUE arg2, ...]);
   *
   *  There is also a special-case arity, INIT_FUNCTION, which corresponds
   *  to void (*)(void) and should never appear in user code.
   *
   *  @note   Currently supports functions with up to receiver + 5 (separate) arguments only!
   *          Anything beyond that should use one of the special arities instead.
   *
   *  @todo   Check for inefficiencies.
   */
  Object* NativeMethod::call(STATE, NativeMethodEnvironment* env, Arguments& args) {
    VALUE receiver = env->get_handle(args.recv());

    switch(arity()->to_int()) {
    case ARGS_IN_RUBY_ARRAY: {  /* Braces required to create objects in a switch */
      VALUE ary = env->get_handle(args.as_array(state));

      VALUE ret = functor_as<OneArgFunctor>()(ary);

      return env->get_object(ret);
    }

    case RECEIVER_PLUS_ARGS_IN_RUBY_ARRAY: {
      VALUE ary = env->get_handle(args.as_array(state));

      VALUE ret = functor_as<TwoArgFunctor>()(receiver, ary);

      return env->get_object(ret);
    }

    case ARG_COUNT_ARGS_IN_C_ARRAY_PLUS_RECEIVER: {
      VALUE* ary = new VALUE[args.total()];

      for (std::size_t i = 0; i < args.total(); ++i) {
        ary[i] = env->get_handle(args.get_argument(i));
      }

      VALUE ret = functor_as<ArgcFunctor>()(args.total(), ary, receiver);

      delete[] ary;

      return env->get_object(ret);
    }

      /*
       *  Normal arg counts
       *
       *  Yes, it is ugly as fuck. It is intended as an encouragement
       *  to get rid of the concept of a separate VALUE and Object.
       */

    case 0: {
      OneArgFunctor functor = functor_as<OneArgFunctor>();

      VALUE ret = functor(receiver);

      return env->get_object(ret);
    }

    case 1: {
      TwoArgFunctor functor = functor_as<TwoArgFunctor>();

      VALUE a1 = env->get_handle(args.get_argument(0));

      VALUE ret = functor(receiver, a1);

      return env->get_object(ret);
    }

    case 2: {
      ThreeArgFunctor functor = functor_as<ThreeArgFunctor>();

      VALUE a1 = env->get_handle(args.get_argument(0));
      VALUE a2 = env->get_handle(args.get_argument(1));

      VALUE ret = functor(receiver, a1, a2);

      return env->get_object(ret);
    }

    case 3: {
      FourArgFunctor functor = functor_as<FourArgFunctor>();
      VALUE a1 = env->get_handle(args.get_argument(0));
      VALUE a2 = env->get_handle(args.get_argument(1));
      VALUE a3 = env->get_handle(args.get_argument(2));

      VALUE ret = functor(receiver, a1, a2, a3);

      return env->get_object(ret);
    }

    case 4: {
      FiveArgFunctor functor = functor_as<FiveArgFunctor>();
      VALUE a1 = env->get_handle(args.get_argument(0));
      VALUE a2 = env->get_handle(args.get_argument(1));
      VALUE a3 = env->get_handle(args.get_argument(2));
      VALUE a4 = env->get_handle(args.get_argument(3));

      VALUE ret = functor(receiver, a1, a2, a3, a4);

      return env->get_object(ret);
    }

    case 5: {
      SixArgFunctor functor = functor_as<SixArgFunctor>();
      VALUE a1 = env->get_handle(args.get_argument(0));
      VALUE a2 = env->get_handle(args.get_argument(1));
      VALUE a3 = env->get_handle(args.get_argument(2));
      VALUE a4 = env->get_handle(args.get_argument(3));
      VALUE a5 = env->get_handle(args.get_argument(4));

      VALUE ret = functor(receiver, a1, a2, a3, a4, a5);

      return env->get_object(ret);
    }

      /* Extension entry point, should never occur for user code. */
    case INIT_FUNCTION: {
      InitFunctor functor = functor_as<InitFunctor>();

      functor();

      return Qnil;
    }

    default:
      capi::capi_raise_runtime_error("unrecognized arity for NativeMethod call");
      return Qnil;
    }
  }

}
<|endoftext|>


<commit_before>/*
** Copyright 2011-2013 Centreon
**
** 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.
**
** For more information : contact@centreon.com
*/

#include <unistd.h>
#include <sys/socket.h>
#include <set>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/watchdog/configuration_parser.hh"
#include "com/centreon/broker/watchdog/application.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/logging/manager.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::watchdog;

int application::sighup_fd[2];
int application::sigterm_fd[2];

/**
 *  Constructor.
 *
 *  @param[in] config_file  The config file.
 */
application::application(std::string const& config_file)
  : _config_path(config_file) {
  // Init the socketpairs used for signal handling.
  if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sighup_fd) != 0
      ||   ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigterm_fd) != 0)
    throw (exceptions::msg() << "watchdog: couldn't init the socketpairs");
  _sighup.reset(new QSocketNotifier(sighup_fd[1], QSocketNotifier::Read, this));
  connect(_sighup.get(), SIGNAL(activated(int)), this, SLOT(handle_sighup()));
  _sigterm.reset(new QSocketNotifier(sigterm_fd[1], QSocketNotifier::Read, this));
  connect(_sigterm.get(), SIGNAL(activated(int)), this, SLOT(handle_sigterm()));

  _init();
}

/**
 *  Destructor.
 */
application::~application() {
  for (std::map<std::string, instance*>::iterator
         it = _instances.begin(),
         end = _instances.end();
       it != end;
       ++it)
    delete it->second;

  logging::manager::unload();
}

/**
 *  Handle sighup.
 */
void application::handle_sighup() {
  _sighup->setEnabled(false);
  char tmp;
  ::read(sighup_fd[1], &tmp, sizeof(tmp));

  configuration config;
  try {
  configuration_parser parser;
  config = parser.parse(_config_path);
  } catch (std::exception const& e) {
    logging::error(logging::medium)
      << "watchdog: couldn't parse the new configuration: " << e.what();
    _sighup->setEnabled(true);
    return;
  }

  _apply_new_configuration(config);
  _sighup->setEnabled(true);
}

/**
 *  Handle sigterm.
 */
void application::handle_sigterm() {
  _sigterm->setEnabled(false);
  char tmp;
  ::read(sigterm_fd[1], &tmp, sizeof(tmp));

  _quit();

  _sigterm->setEnabled(true);
}

/**
 *  Initialize the application.
 */
void application::_init() {
  // Parse the configuration.
  configuration_parser parser;
  configuration config = parser.parse(_config_path);

  // Load the log manager.
  logging::manager::load();

  // Apply the configuration.
  _apply_new_configuration(config);
}

/**
 *  Apply a new configuration.
 *
 *  @param[in] config  The new configuration.
 */
void application::_apply_new_configuration(configuration const& config) {
  // Create the log file backend if needed.
  if (_config.get_log_filename() != config.get_log_filename()) {
    _log.reset(new logging::file(
                      QString::fromStdString(config.get_log_filename())));
    logging::manager::instance().log_on(*_log);
  }

  std::set<std::string> to_update;
  std::set<std::string> to_delete;
  std::set<std::string> to_create;

  // Old configs that aren't present in the new should be deleted and recreated.
  // Old configs that are present in the new should be updated.
  for (configuration::instance_map::const_iterator
         it = _config.get_instances_configuration().begin(),
         end = _config.get_instances_configuration().end();
       it != end;
       ++it) {
    instance_configuration new_config
      = config.get_instance_configuration(it->first);
    if (new_config != it->second) {
      to_delete.insert(it->first);
      to_create.insert(it->first);
    }
    else
      to_update.insert(it->first);
  }

  // New configs that aren't present in the old should be created.
  for (configuration::instance_map::const_iterator
       it = config.get_instances_configuration().begin(),
       end = config.get_instances_configuration().end();
     it != end;
     ++it)
    if (!_config.instance_exists(it->first))
      to_create.insert(it->first);

  // Delete old processes.
  for (std::set<std::string>::const_iterator
         it = to_delete.begin(),
         end = to_delete.end();
       it != end;
       ++it) {
    std::map<std::string, instance*>::iterator found = _instances.find(*it);
    if (found != _instances.end()) {
      delete found->second;
      _instances.erase(found);
    }
  }

  // Update processes.
  for (std::set<std::string>::const_iterator
         it = to_update.begin(),
         end = to_update.end();
       it != end;
       ++it) {
    std::map<std::string, instance*>::iterator found = _instances.find(*it);
    if (found != _instances.end()) {
      found->second->merge_configuration(
        config.get_instance_configuration(*it));
      found->second->update_instance();
    }
  }

  // Start new processes.
  for (std::set<std::string>::const_iterator
         it = to_create.begin(),
         end = to_create.end();
       it != end;
       ++it) {
    std::auto_ptr<instance> ins(
      new instance(config.get_instance_configuration(*it), *this));
    _instances.insert(std::make_pair(*it, ins.release()));
  }

  // Save the new configuration.
  _config = config;
}

/**
 *  Quit the application and subinstances.
 */
void application::_quit() {
  logging::info(logging::medium)
    << "watchdog: exiting";
  for (std::map<std::string, instance*>::iterator
         it = _instances.begin(),
         end = _instances.end();
       it != end;
       ++it)
    it->second->stop_instance();
  exit();
}
<commit_msg>Watchdog: fix bad logic.<commit_after>/*
** Copyright 2011-2013 Centreon
**
** 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.
**
** For more information : contact@centreon.com
*/

#include <unistd.h>
#include <sys/socket.h>
#include <set>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/watchdog/configuration_parser.hh"
#include "com/centreon/broker/watchdog/application.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/logging/manager.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::watchdog;

int application::sighup_fd[2];
int application::sigterm_fd[2];

/**
 *  Constructor.
 *
 *  @param[in] config_file  The config file.
 */
application::application(std::string const& config_file)
  : _config_path(config_file) {
  // Init the socketpairs used for signal handling.
  if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sighup_fd) != 0
      ||   ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigterm_fd) != 0)
    throw (exceptions::msg() << "watchdog: couldn't init the socketpairs");
  _sighup.reset(new QSocketNotifier(sighup_fd[1], QSocketNotifier::Read, this));
  connect(_sighup.get(), SIGNAL(activated(int)), this, SLOT(handle_sighup()));
  _sigterm.reset(new QSocketNotifier(sigterm_fd[1], QSocketNotifier::Read, this));
  connect(_sigterm.get(), SIGNAL(activated(int)), this, SLOT(handle_sigterm()));

  _init();
}

/**
 *  Destructor.
 */
application::~application() {
  for (std::map<std::string, instance*>::iterator
         it = _instances.begin(),
         end = _instances.end();
       it != end;
       ++it)
    delete it->second;

  logging::manager::unload();
}

/**
 *  Handle sighup.
 */
void application::handle_sighup() {
  _sighup->setEnabled(false);
  char tmp;
  ::read(sighup_fd[1], &tmp, sizeof(tmp));

  configuration config;
  try {
  configuration_parser parser;
  config = parser.parse(_config_path);
  } catch (std::exception const& e) {
    logging::error(logging::medium)
      << "watchdog: couldn't parse the new configuration: " << e.what();
    _sighup->setEnabled(true);
    return;
  }

  _apply_new_configuration(config);
  _sighup->setEnabled(true);
}

/**
 *  Handle sigterm.
 */
void application::handle_sigterm() {
  _sigterm->setEnabled(false);
  char tmp;
  ::read(sigterm_fd[1], &tmp, sizeof(tmp));

  _quit();

  _sigterm->setEnabled(true);
}

/**
 *  Initialize the application.
 */
void application::_init() {
  // Parse the configuration.
  configuration_parser parser;
  configuration config = parser.parse(_config_path);

  // Load the log manager.
  logging::manager::load();

  // Apply the configuration.
  _apply_new_configuration(config);
}

/**
 *  Apply a new configuration.
 *
 *  @param[in] config  The new configuration.
 */
void application::_apply_new_configuration(configuration const& config) {
  // Create the log file backend if needed.
  if (_config.get_log_filename() != config.get_log_filename()) {
    _log.reset(new logging::file(
                      QString::fromStdString(config.get_log_filename())));
    logging::manager::instance().log_on(*_log);
  }

  std::set<std::string> to_update;
  std::set<std::string> to_delete;
  std::set<std::string> to_create;

  // Old configs that aren't present in the new should be deleted.
  // Old configs that are present in the new should be updated
  // or deleted/recreated.
  for (configuration::instance_map::const_iterator
         it = _config.get_instances_configuration().begin(),
         end = _config.get_instances_configuration().end();
       it != end;
       ++it) {
    instance_configuration new_config
      = config.get_instance_configuration(it->first);
    if (new_config.is_empty())
      to_delete.insert(it->first);
    else if (new_config != it->second) {
      to_delete.insert(it->first);
      to_create.insert(it->first);
    }
    else
      to_update.insert(it->first);
  }

  // New configs that aren't present in the old should be created.
  for (configuration::instance_map::const_iterator
       it = config.get_instances_configuration().begin(),
       end = config.get_instances_configuration().end();
     it != end;
     ++it)
    if (!_config.instance_exists(it->first))
      to_create.insert(it->first);

  // Delete old processes.
  for (std::set<std::string>::const_iterator
         it = to_delete.begin(),
         end = to_delete.end();
       it != end;
       ++it) {
    std::map<std::string, instance*>::iterator found = _instances.find(*it);
    if (found != _instances.end()) {
      delete found->second;
      _instances.erase(found);
    }
  }

  // Update processes.
  for (std::set<std::string>::const_iterator
         it = to_update.begin(),
         end = to_update.end();
       it != end;
       ++it) {
    std::map<std::string, instance*>::iterator found = _instances.find(*it);
    if (found != _instances.end()) {
      found->second->merge_configuration(
        config.get_instance_configuration(*it));
      found->second->update_instance();
    }
  }

  // Start new processes.
  for (std::set<std::string>::const_iterator
         it = to_create.begin(),
         end = to_create.end();
       it != end;
       ++it) {
    std::auto_ptr<instance> ins(
      new instance(config.get_instance_configuration(*it), *this));
    _instances.insert(std::make_pair(*it, ins.release()));
  }

  // Save the new configuration.
  _config = config;
}

/**
 *  Quit the application and subinstances.
 */
void application::_quit() {
  logging::info(logging::medium)
    << "watchdog: exiting";
  for (std::map<std::string, instance*>::iterator
         it = _instances.begin(),
         end = _instances.end();
       it != end;
       ++it)
    it->second->stop_instance();
  exit();
}
<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/CIFactory.h"

#include "DeclCollector.h"

#include "clang/AST/ASTContext.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Preprocessor.h"

#include "llvm/LLVMContext.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"

using namespace clang;

namespace cling {
  //
  //  Dummy function so we can use dladdr to find the executable path.
  //
  void locate_cling_executable()
  {
  }

  /// \brief Retrieves the clang CC1 specific flags out of the compilation's
  /// jobs. Returns NULL on error.
  static const clang::driver::ArgStringList
  *GetCC1Arguments(clang::DiagnosticsEngine *Diagnostics,
                   clang::driver::Compilation *Compilation) {
    // We expect to get back exactly one Command job, if we didn't something
    // failed. Extract that job from the Compilation.
    const clang::driver::JobList &Jobs = Compilation->getJobs();
    if (!Jobs.size() || !isa<clang::driver::Command>(*Jobs.begin())) {
      // diagnose this...
      return NULL;
    }

    // The one job we find should be to invoke clang again.
    const clang::driver::Command *Cmd
      = cast<clang::driver::Command>(*Jobs.begin());
    if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
      // diagnose this...
      return NULL;
    }

    return &Cmd->getArguments();
  }

  CompilerInstance* CIFactory::createCI(llvm::StringRef code,
                                        int argc,
                                        const char* const *argv,
                                        const char* llvmdir) {
    return createCI(llvm::MemoryBuffer::getMemBuffer(code), argc, argv,
                    llvmdir);
  }

  CompilerInstance* CIFactory::createCI(llvm::MemoryBuffer* buffer,
                                        int argc,
                                        const char* const *argv,
                                        const char* llvmdir) {
    // Create an instance builder, passing the llvmdir and arguments.
    //
    //  Initialize the llvm library.
    llvm::InitializeNativeTarget();
    llvm::InitializeAllAsmPrinters();
    llvm::sys::Path resource_path;
    if (llvmdir) {
      resource_path = llvmdir;
      resource_path.appendComponent("lib");
      resource_path.appendComponent("clang");
      resource_path.appendComponent(CLANG_VERSION_STRING);
    } else {
      // FIXME: The first arg really does need to be argv[0] on FreeBSD.
      //
      // Note: The second arg is not used for Apple, FreeBSD, Linux,
      //       or cygwin, and can only be used on systems which support
      //       the use of dladdr().
      //
      // Note: On linux and cygwin this uses /proc/self/exe to find the path.
      //
      // Note: On Apple it uses _NSGetExecutablePath().
      //
      // Note: On FreeBSD it uses getprogpath().
      //
      // Note: Otherwise it uses dladdr().
      //
      resource_path
        = CompilerInvocation::GetResourcesPath("cling",
                                       (void*)(intptr_t) locate_cling_executable
                                               );
    }
    if (!resource_path.canRead()) {
      llvm::errs()
        << "ERROR in cling::CIFactory::createCI():\n  resource directory "
        << resource_path.str() << " not found!\n";
      resource_path = "";
    }

    //______________________________________
    DiagnosticOptions DefaultDiagnosticOptions;
    DefaultDiagnosticOptions.ShowColors = 1;
    TextDiagnosticPrinter* DiagnosticPrinter
      = new TextDiagnosticPrinter(llvm::errs(), DefaultDiagnosticOptions);
    llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(new DiagnosticIDs());
    DiagnosticsEngine* Diagnostics
      = new DiagnosticsEngine(DiagIDs, DiagnosticPrinter,
                              /*Owns it*/ true); // LEAKS!

    std::vector<const char*> argvCompile(argv, argv + argc);
    // We do C++ by default; append right after argv[0] name
    // Only insert it if there is no other "-x":
    bool haveMinusX = false;
    for (const char* const* iarg = argv; !haveMinusX && iarg < argv + argc;
         ++iarg) {
      haveMinusX = !strcmp(*iarg, "-x");
    }
    if (!haveMinusX) {
      argvCompile.insert(argvCompile.begin() + 1,"-x");
      argvCompile.insert(argvCompile.begin() + 2, "c++");
    }
    argvCompile.push_back("-c");
    argvCompile.push_back("-");

    bool IsProduction = false;
    assert(IsProduction = true && "set IsProduction if asserts are on.");
    clang::driver::Driver Driver(argv[0], llvm::sys::getDefaultTargetTriple(),
                                 "cling.out",
                                 IsProduction,
                                 *Diagnostics);
    //Driver.setWarnMissingInput(false);
    Driver.setCheckInputsExist(false); // think foo.C(12)
    llvm::ArrayRef<const char*>RF(&(argvCompile[0]), argvCompile.size());
    llvm::OwningPtr<clang::driver::Compilation>
      Compilation(Driver.BuildCompilation(RF));
    const clang::driver::ArgStringList* CC1Args
      = GetCC1Arguments(Diagnostics, Compilation.get());
    if (CC1Args == NULL) {
      return 0;
    }
    clang::CompilerInvocation*
      Invocation = new clang::CompilerInvocation; // LEAKS!
    clang::CompilerInvocation::CreateFromArgs(*Invocation, CC1Args->data() + 1,
                                              CC1Args->data() + CC1Args->size(),
                                              *Diagnostics);
    Invocation->getFrontendOpts().DisableFree = true;

    if (Invocation->getHeaderSearchOpts().UseBuiltinIncludes &&
        !resource_path.empty()) {
      // Update ResourceDir
      // header search opts' entry for resource_path/include isn't
      // updated by providing a new resource path; update it manually.
      clang::HeaderSearchOptions& Opts = Invocation->getHeaderSearchOpts();
      llvm::sys::Path oldResInc(Opts.ResourceDir);
      oldResInc.appendComponent("include");
      llvm::sys::Path newResInc(resource_path);
      newResInc.appendComponent("include");
      bool foundOldResInc = false;
      for (unsigned i = 0, e = Opts.UserEntries.size();
           !foundOldResInc && i != e; ++i) {
        HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
        if (!E.IsUserSupplied && !E.IsFramework
            && E.Group == clang::frontend::System && E.IgnoreSysRoot
            && E.IsInternal && !E.ImplicitExternC
            && oldResInc.str() == E.Path) {
          E.Path = newResInc.str();
          foundOldResInc = true;
        }
      }

      Opts.ResourceDir = resource_path.str();
    }

    // Create and setup a compiler instance.
    CompilerInstance* CI = new CompilerInstance();
    CI->setInvocation(Invocation);

    CI->createDiagnostics(CC1Args->size(), CC1Args->data() + 1);
    {
      //
      //  Buffer the error messages while we process
      //  the compiler options.
      //

      // Set the language options, which cling needs
      SetClingCustomLangOpts(CI->getLangOpts());

      CI->getInvocation().getPreprocessorOpts().addMacroDef("__CLING__");
      if (CI->getDiagnostics().hasErrorOccurred()) {
        delete CI;
        CI = 0;
        return 0;
      }
    }
    CI->setTarget(TargetInfo::CreateTargetInfo(CI->getDiagnostics(),
                                               Invocation->getTargetOpts()));
    if (!CI->hasTarget()) {
      delete CI;
      CI = 0;
      return 0;
    }
    CI->getTarget().setForcedLangOptions(CI->getLangOpts());
    SetClingTargetLangOpts(CI->getLangOpts(), CI->getTarget());

    // Set up source and file managers
    CI->createFileManager();
    CI->createSourceManager(CI->getFileManager());

    // Set up the memory buffer
    if (buffer)
      CI->getSourceManager().createMainFileIDForMemBuffer(buffer);

    // Set up the preprocessor
    CI->createPreprocessor();
    Preprocessor& PP = CI->getPreprocessor();
    PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
                                           PP.getLangOpts());

    // Set up the ASTContext
    ASTContext *Ctx = new ASTContext(CI->getLangOpts(),
                                     PP.getSourceManager(), &CI->getTarget(),
                                     PP.getIdentifierTable(),
                                     PP.getSelectorTable(), PP.getBuiltinInfo(),
                                     /*size_reserve*/0, /*DelayInit*/false);
    CI->setASTContext(Ctx);

    // Set up the ASTConsumers
    CI->setASTConsumer(new DeclCollector());

    // Set up Sema
    CodeCompleteConsumer* CCC = 0;
    CI->createSema(TU_Prefix, CCC);

    // Set CodeGen options
    // CI->getCodeGenOpts().DebugInfo = 1; // want debug info
    // CI->getCodeGenOpts().EmitDeclMetadata = 1; // For unloading, for later
    CI->getCodeGenOpts().OptimizationLevel = 0; // see pure SSA, that comes out
    // When asserts are on, TURN ON not compare the VerifyModule
    assert(CI->getCodeGenOpts().VerifyModule = 1);
    return CI;
  }

  void CIFactory::SetClingCustomLangOpts(LangOptions& Opts) {
    Opts.EmitAllDecls = 1;
    Opts.Exceptions = 1;
    Opts.CXXExceptions = 1;
    Opts.Deprecated = 1;
  }

  void CIFactory::SetClingTargetLangOpts(LangOptions& Opts,
                                         const TargetInfo& Target) {
    if (Target.getTriple().getOS() == llvm::Triple::Win32) {
      Opts.MicrosoftExt = 1;
      Opts.MSCVersion = 1300;
      // Should fix http://llvm.org/bugs/show_bug.cgi?id=10528
      Opts.DelayedTemplateParsing = 1;
    } else {
      Opts.MicrosoftExt = 0;
    }
  }
} // end namespace
<commit_msg>Enable Modules by default for cling.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/CIFactory.h"

#include "DeclCollector.h"

#include "clang/AST/ASTContext.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Preprocessor.h"

#include "llvm/LLVMContext.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"

using namespace clang;

namespace cling {
  //
  //  Dummy function so we can use dladdr to find the executable path.
  //
  void locate_cling_executable()
  {
  }

  /// \brief Retrieves the clang CC1 specific flags out of the compilation's
  /// jobs. Returns NULL on error.
  static const clang::driver::ArgStringList
  *GetCC1Arguments(clang::DiagnosticsEngine *Diagnostics,
                   clang::driver::Compilation *Compilation) {
    // We expect to get back exactly one Command job, if we didn't something
    // failed. Extract that job from the Compilation.
    const clang::driver::JobList &Jobs = Compilation->getJobs();
    if (!Jobs.size() || !isa<clang::driver::Command>(*Jobs.begin())) {
      // diagnose this...
      return NULL;
    }

    // The one job we find should be to invoke clang again.
    const clang::driver::Command *Cmd
      = cast<clang::driver::Command>(*Jobs.begin());
    if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
      // diagnose this...
      return NULL;
    }

    return &Cmd->getArguments();
  }

  CompilerInstance* CIFactory::createCI(llvm::StringRef code,
                                        int argc,
                                        const char* const *argv,
                                        const char* llvmdir) {
    return createCI(llvm::MemoryBuffer::getMemBuffer(code), argc, argv,
                    llvmdir);
  }

  CompilerInstance* CIFactory::createCI(llvm::MemoryBuffer* buffer,
                                        int argc,
                                        const char* const *argv,
                                        const char* llvmdir) {
    // Create an instance builder, passing the llvmdir and arguments.
    //
    //  Initialize the llvm library.
    llvm::InitializeNativeTarget();
    llvm::InitializeAllAsmPrinters();
    llvm::sys::Path resource_path;
    if (llvmdir) {
      resource_path = llvmdir;
      resource_path.appendComponent("lib");
      resource_path.appendComponent("clang");
      resource_path.appendComponent(CLANG_VERSION_STRING);
    } else {
      // FIXME: The first arg really does need to be argv[0] on FreeBSD.
      //
      // Note: The second arg is not used for Apple, FreeBSD, Linux,
      //       or cygwin, and can only be used on systems which support
      //       the use of dladdr().
      //
      // Note: On linux and cygwin this uses /proc/self/exe to find the path.
      //
      // Note: On Apple it uses _NSGetExecutablePath().
      //
      // Note: On FreeBSD it uses getprogpath().
      //
      // Note: Otherwise it uses dladdr().
      //
      resource_path
        = CompilerInvocation::GetResourcesPath("cling",
                                       (void*)(intptr_t) locate_cling_executable
                                               );
    }
    if (!resource_path.canRead()) {
      llvm::errs()
        << "ERROR in cling::CIFactory::createCI():\n  resource directory "
        << resource_path.str() << " not found!\n";
      resource_path = "";
    }

    //______________________________________
    DiagnosticOptions DefaultDiagnosticOptions;
    DefaultDiagnosticOptions.ShowColors = 1;
    TextDiagnosticPrinter* DiagnosticPrinter
      = new TextDiagnosticPrinter(llvm::errs(), DefaultDiagnosticOptions);
    llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(new DiagnosticIDs());
    DiagnosticsEngine* Diagnostics
      = new DiagnosticsEngine(DiagIDs, DiagnosticPrinter,
                              /*Owns it*/ true); // LEAKS!

    std::vector<const char*> argvCompile(argv, argv + argc);
    // We do C++ by default; append right after argv[0] name
    // Only insert it if there is no other "-x":
    bool haveMinusX = false;
    for (const char* const* iarg = argv; !haveMinusX && iarg < argv + argc;
         ++iarg) {
      haveMinusX = !strcmp(*iarg, "-x");
    }
    if (!haveMinusX) {
      argvCompile.insert(argvCompile.begin() + 1,"-x");
      argvCompile.insert(argvCompile.begin() + 2, "c++");
    }
    argvCompile.push_back("-c");
    argvCompile.push_back("-");

    bool IsProduction = false;
    assert(IsProduction = true && "set IsProduction if asserts are on.");
    clang::driver::Driver Driver(argv[0], llvm::sys::getDefaultTargetTriple(),
                                 "cling.out",
                                 IsProduction,
                                 *Diagnostics);
    //Driver.setWarnMissingInput(false);
    Driver.setCheckInputsExist(false); // think foo.C(12)
    llvm::ArrayRef<const char*>RF(&(argvCompile[0]), argvCompile.size());
    llvm::OwningPtr<clang::driver::Compilation>
      Compilation(Driver.BuildCompilation(RF));
    const clang::driver::ArgStringList* CC1Args
      = GetCC1Arguments(Diagnostics, Compilation.get());
    if (CC1Args == NULL) {
      return 0;
    }
    clang::CompilerInvocation*
      Invocation = new clang::CompilerInvocation; // LEAKS!
    clang::CompilerInvocation::CreateFromArgs(*Invocation, CC1Args->data() + 1,
                                              CC1Args->data() + CC1Args->size(),
                                              *Diagnostics);
    Invocation->getFrontendOpts().DisableFree = true;

    if (Invocation->getHeaderSearchOpts().UseBuiltinIncludes &&
        !resource_path.empty()) {
      // Update ResourceDir
      // header search opts' entry for resource_path/include isn't
      // updated by providing a new resource path; update it manually.
      clang::HeaderSearchOptions& Opts = Invocation->getHeaderSearchOpts();
      llvm::sys::Path oldResInc(Opts.ResourceDir);
      oldResInc.appendComponent("include");
      llvm::sys::Path newResInc(resource_path);
      newResInc.appendComponent("include");
      bool foundOldResInc = false;
      for (unsigned i = 0, e = Opts.UserEntries.size();
           !foundOldResInc && i != e; ++i) {
        HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
        if (!E.IsUserSupplied && !E.IsFramework
            && E.Group == clang::frontend::System && E.IgnoreSysRoot
            && E.IsInternal && !E.ImplicitExternC
            && oldResInc.str() == E.Path) {
          E.Path = newResInc.str();
          foundOldResInc = true;
        }
      }

      Opts.ResourceDir = resource_path.str();
    }

    // Create and setup a compiler instance.
    CompilerInstance* CI = new CompilerInstance();
    CI->setInvocation(Invocation);

    CI->createDiagnostics(CC1Args->size(), CC1Args->data() + 1);
    {
      //
      //  Buffer the error messages while we process
      //  the compiler options.
      //

      // Set the language options, which cling needs
      SetClingCustomLangOpts(CI->getLangOpts());

      CI->getInvocation().getPreprocessorOpts().addMacroDef("__CLING__");
      if (CI->getDiagnostics().hasErrorOccurred()) {
        delete CI;
        CI = 0;
        return 0;
      }
    }
    CI->setTarget(TargetInfo::CreateTargetInfo(CI->getDiagnostics(),
                                               Invocation->getTargetOpts()));
    if (!CI->hasTarget()) {
      delete CI;
      CI = 0;
      return 0;
    }
    CI->getTarget().setForcedLangOptions(CI->getLangOpts());
    SetClingTargetLangOpts(CI->getLangOpts(), CI->getTarget());

    // Set up source and file managers
    CI->createFileManager();
    CI->createSourceManager(CI->getFileManager());

    // Set up the memory buffer
    if (buffer)
      CI->getSourceManager().createMainFileIDForMemBuffer(buffer);

    // Set up the preprocessor
    CI->createPreprocessor();
    Preprocessor& PP = CI->getPreprocessor();
    PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
                                           PP.getLangOpts());

    // Set up the ASTContext
    ASTContext *Ctx = new ASTContext(CI->getLangOpts(),
                                     PP.getSourceManager(), &CI->getTarget(),
                                     PP.getIdentifierTable(),
                                     PP.getSelectorTable(), PP.getBuiltinInfo(),
                                     /*size_reserve*/0, /*DelayInit*/false);
    CI->setASTContext(Ctx);

    // Set up the ASTConsumers
    CI->setASTConsumer(new DeclCollector());

    // Set up Sema
    CodeCompleteConsumer* CCC = 0;
    CI->createSema(TU_Prefix, CCC);

    // Set CodeGen options
    // CI->getCodeGenOpts().DebugInfo = 1; // want debug info
    // CI->getCodeGenOpts().EmitDeclMetadata = 1; // For unloading, for later
    CI->getCodeGenOpts().OptimizationLevel = 0; // see pure SSA, that comes out
    // When asserts are on, TURN ON not compare the VerifyModule
    assert(CI->getCodeGenOpts().VerifyModule = 1);
    return CI;
  }

  void CIFactory::SetClingCustomLangOpts(LangOptions& Opts) {
    Opts.EmitAllDecls = 1;
    Opts.Exceptions = 1;
    Opts.CXXExceptions = 1;
    Opts.Deprecated = 1;
    Opts.Modules = 1;
  }

  void CIFactory::SetClingTargetLangOpts(LangOptions& Opts,
                                         const TargetInfo& Target) {
    if (Target.getTriple().getOS() == llvm::Triple::Win32) {
      Opts.MicrosoftExt = 1;
      Opts.MSCVersion = 1300;
      // Should fix http://llvm.org/bugs/show_bug.cgi?id=10528
      Opts.DelayedTemplateParsing = 1;
    } else {
      Opts.MicrosoftExt = 0;
    }
  }
} // end namespace
<|endoftext|>


<commit_before>#ifndef K3_RUNTIME_BASETYPES_H
#define K3_RUNTIME_BASETYPES_H

#include "boost/functional/hash.hpp"
#include "serialization/yaml.hpp"
// Basic types needed by our builtin libraries

class unit_t {
  public:
  template <class archive>
  void serialize(archive&, const unsigned int) {}
  bool operator==(const unit_t& r) const { return true; }
  bool operator!=(const unit_t& r) const { return false; }
  bool operator<(const unit_t& r) const { return false; }
  bool operator>(const unit_t& r) const { return false; }
};

namespace YAML {
  template <>
  class convert<unit_t> {
    public:
        static Node encode(const unit_t& r)  {
          Node node;
          return node;
        }
        static bool decode(const Node& node, unit_t& r)  {
          return true;
        }
  };
}

#ifndef K3_R_addr
#define K3_R_addr
template <class _T0>
class R_addr {
    public:
        R_addr() {}
        R_addr(_T0 _addr): addr(_addr) {}
        R_addr(const R_addr<_T0>& _r): addr(_r.addr) {}
        bool operator==(const R_addr& _r) const {
            if (addr == _r.addr)
                return true;
            return false;
        }
        bool operator!=(const R_addr& _r) const {
            return !(*this == _r);
        }
        bool operator<(const R_addr& _r) const {
          return addr < _r.addr;
        }
        template <class archive>
        void serialize(archive& _archive,const unsigned int) {
            _archive & addr;

        }
        _T0 addr;
};

#endif // K3_R_addr

#ifndef K3_R_addr_hash_value
#define K3_R_addr_hash_value
template <class T>
  std::size_t hash_value(R_addr<T> const& b) {
    boost::hash<T> hasher;
    return hasher(b.addr);
}
#endif // K3_R_addr_hash_value

#ifndef K3_R_elem
#define K3_R_elem

template <class _T0>
class R_elem {
    public:
        R_elem() {}
        R_elem(_T0 _elem): elem(_elem) {}
        R_elem(const R_elem<_T0>& _r): elem(_r.elem) {}
        bool operator==(const R_elem& _r) const {
            if (elem == _r.elem)
                return true;
            return false;
        }
        // TODO, beter implementation?
        bool operator!=(const R_elem& _r) const {
            return !(*this == _r);
        }
        bool operator<(const R_elem& _r) const {
            return elem < _r.elem;
        }
        template <class archive>
        void serialize(archive& _archive,const unsigned int) {
            _archive & elem;
        }
        _T0 elem;
};
#endif // K3_R_elem

#ifndef K3_R_elem_hash_value
#define K3_R_elem_hash_value
template <class T>
  std::size_t hash_value(R_elem<T> const& b) {
    boost::hash<T> hasher;
    return hasher(b.elem);
}
#endif // K3_R_elem_hash_value

#ifndef K3_R_key_value
#define K3_R_key_value

template <class _T0, class _T1>
class R_key_value {
  public:
      typedef _T0 KeyType;
      typedef _T1 ValueType;
      R_key_value(): key(), value()  {}
      template <class __T0, class __T1>
      R_key_value(__T0&& _key, __T1&& _value): key(std::forward<__T0>(_key)),
      value(std::forward<__T1>(_value))  {}
      R_key_value(const R_key_value<_T0, _T1>& __other): key(__other.key), value(__other.value)  {}
      R_key_value(R_key_value<_T0, _T1>&& __other): key(std::move(__other.key)),
      value(std::move(__other.value))  {}
      template <class archive>
      void serialize(archive& _archive, const unsigned int)  {
        _archive & key;
        _archive & value;
      }
      R_key_value<_T0, _T1>& operator=(const R_key_value<_T0, _T1>& __other)  {
        key = (__other.key);
        value = (__other.value);
        return *(this);
      }
      R_key_value<_T0, _T1>& operator=(R_key_value<_T0, _T1>&& __other)  {
        key = std::move(__other.key);
        value = std::move(__other.value);
        return *(this);
      }
      bool operator==(const R_key_value<_T0, _T1>& __other) const {
        return key == (__other.key) && value == (__other.value);
      }
      bool operator!=(const R_key_value<_T0, _T1>& __other) const {
        return std::tie(key, value) != std::tie(__other.key, __other.value);
      }
      bool operator<(const R_key_value<_T0, _T1>& __other) const {
        return std::tie(key, value) < std::tie(__other.key, __other.value);
      }
      bool operator>(const R_key_value<_T0, _T1>& __other) const {
        return std::tie(key, value) > std::tie(__other.key, __other.value);
      }
      _T0 key;
      _T1 value;
};

#endif // K3_R_key_value

#ifndef K3_R_key_value_hash_value
#define K3_R_key_value_hash_value
template <class K,class V>
  std::size_t hash_value(R_key_value<K,V> const& b) {
    boost::hash<std::tuple<K,V>> hasher;
    return hasher(std::tie(b.key, b.value));
}
#endif // K3_R_key_value_hash_value

#endif // K3_RUNTIME_BASETYPES_H
<commit_msg>Warning cleanup in BaseTypes.<commit_after>#ifndef K3_RUNTIME_BASETYPES_H
#define K3_RUNTIME_BASETYPES_H

#include "boost/functional/hash.hpp"
#include "serialization/yaml.hpp"
// Basic types needed by our builtin libraries

class unit_t {
  public:
  template <class archive>
  void serialize(archive&, const unsigned int) {}
  bool operator==(const unit_t&) const { return true; }
  bool operator!=(const unit_t&) const { return false; }
  bool operator<(const unit_t&) const { return false; }
  bool operator>(const unit_t&) const { return false; }
};

namespace YAML {
  template <>
  struct convert<unit_t> {
    public:
        static Node encode(const unit_t&)  {
          Node node;
          return node;
        }
        static bool decode(const Node&, unit_t&)  {
          return true;
        }
  };
}

#ifndef K3_R_addr
#define K3_R_addr
template <class _T0>
class R_addr {
    public:
        R_addr() {}
        R_addr(_T0 _addr): addr(_addr) {}
        R_addr(const R_addr<_T0>& _r): addr(_r.addr) {}
        bool operator==(const R_addr& _r) const {
            if (addr == _r.addr)
                return true;
            return false;
        }
        bool operator!=(const R_addr& _r) const {
            return !(*this == _r);
        }
        bool operator<(const R_addr& _r) const {
          return addr < _r.addr;
        }
        template <class archive>
        void serialize(archive& _archive,const unsigned int) {
            _archive & addr;

        }
        _T0 addr;
};

#endif // K3_R_addr

#ifndef K3_R_addr_hash_value
#define K3_R_addr_hash_value
template <class T>
  std::size_t hash_value(R_addr<T> const& b) {
    boost::hash<T> hasher;
    return hasher(b.addr);
}
#endif // K3_R_addr_hash_value

#ifndef K3_R_elem
#define K3_R_elem

template <class _T0>
class R_elem {
    public:
        R_elem() {}
        R_elem(_T0 _elem): elem(_elem) {}
        R_elem(const R_elem<_T0>& _r): elem(_r.elem) {}
        bool operator==(const R_elem& _r) const {
            if (elem == _r.elem)
                return true;
            return false;
        }
        // TODO, beter implementation?
        bool operator!=(const R_elem& _r) const {
            return !(*this == _r);
        }
        bool operator<(const R_elem& _r) const {
            return elem < _r.elem;
        }
        template <class archive>
        void serialize(archive& _archive,const unsigned int) {
            _archive & elem;
        }
        _T0 elem;
};
#endif // K3_R_elem

#ifndef K3_R_elem_hash_value
#define K3_R_elem_hash_value
template <class T>
  std::size_t hash_value(R_elem<T> const& b) {
    boost::hash<T> hasher;
    return hasher(b.elem);
}
#endif // K3_R_elem_hash_value

#ifndef K3_R_key_value
#define K3_R_key_value

template <class _T0, class _T1>
class R_key_value {
  public:
      typedef _T0 KeyType;
      typedef _T1 ValueType;
      R_key_value(): key(), value()  {}
      template <class __T0, class __T1>
      R_key_value(__T0&& _key, __T1&& _value): key(std::forward<__T0>(_key)),
      value(std::forward<__T1>(_value))  {}
      R_key_value(const R_key_value<_T0, _T1>& __other): key(__other.key), value(__other.value)  {}
      R_key_value(R_key_value<_T0, _T1>&& __other): key(std::move(__other.key)),
      value(std::move(__other.value))  {}
      template <class archive>
      void serialize(archive& _archive, const unsigned int)  {
        _archive & key;
        _archive & value;
      }
      R_key_value<_T0, _T1>& operator=(const R_key_value<_T0, _T1>& __other)  {
        key = (__other.key);
        value = (__other.value);
        return *(this);
      }
      R_key_value<_T0, _T1>& operator=(R_key_value<_T0, _T1>&& __other)  {
        key = std::move(__other.key);
        value = std::move(__other.value);
        return *(this);
      }
      bool operator==(const R_key_value<_T0, _T1>& __other) const {
        return key == (__other.key) && value == (__other.value);
      }
      bool operator!=(const R_key_value<_T0, _T1>& __other) const {
        return std::tie(key, value) != std::tie(__other.key, __other.value);
      }
      bool operator<(const R_key_value<_T0, _T1>& __other) const {
        return std::tie(key, value) < std::tie(__other.key, __other.value);
      }
      bool operator>(const R_key_value<_T0, _T1>& __other) const {
        return std::tie(key, value) > std::tie(__other.key, __other.value);
      }
      _T0 key;
      _T1 value;
};

#endif // K3_R_key_value

#ifndef K3_R_key_value_hash_value
#define K3_R_key_value_hash_value
template <class K,class V>
  std::size_t hash_value(R_key_value<K,V> const& b) {
    boost::hash<std::tuple<K,V>> hasher;
    return hasher(std::tie(b.key, b.value));
}
#endif // K3_R_key_value_hash_value

#endif // K3_RUNTIME_BASETYPES_H
<|endoftext|>