<commit_before>#include <assert.h>
#include <cstdio>

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/IRReader/IRReader.h>

#include <iostream>
#include <string>

#include "../src/LLVMDependenceGraph.h"

using namespace dg;
using llvm::errs;

static struct {
#if ENABLE_CFG
    bool printCFG;
    bool printRevCFG;
    bool printBB;
#endif

    bool printControlDep;
    bool printDataDep;
} OPTIONS;

static std::string& getValueName(const llvm::Value *val, std::string &str)
{
    llvm::raw_string_ostream s(str);

    str.clear();

    if (!val) {
        s << "[NULL]";
        return s.str();
    }

    if (llvm::isa<llvm::Function>(val))
        s << "ENTRY " << val->getName();
    else
        s << *val;

    return s.str();
}

static void dump_to_dot(LLVMDGNode *n, std::ostream& out)
{
    const llvm::Value *val;

    /* do not draw multiple edges */
    if (n->getDFSrun() == 1)
        return;
    else
        n->setDFSrun(1);

    if (OPTIONS.printControlDep)
        for (auto I = n->control_begin(), E = n->control_end();
             I != E; ++I)
            out << "\tNODE" << n << " -> NODE" <<  *I << "\n";

    if (OPTIONS.printDataDep)
        for (auto I = n->dependence_begin(), E = n->dependence_end();
             I != E; ++I)
            out << "\tNODE" << n << " -> NODE" <<  *I
                << " [color=red]\n";

#if ENABLE_CFG
    if (OPTIONS.printCFG)
        for (auto I = n->succ_begin(), E = n->succ_end();
             I != E; ++I)
            out << "\tNODE" << n << " -> NODE" <<  *I
                << " [style=dotted]\n";
    if (OPTIONS.printRevCFG)
        for (auto I = n->pred_begin(), E = n->pred_end();
             I != E; ++I)
            out << "\tNODE" << n << " -> NODE" <<  *I
                << " [style=dotted color=gray]\n";
    if (OPTIONS.printBB) {
        auto BB = n->getBasicBlock();
        // if this is BB header, print the edges
        if (BB && BB->getFirstNode() == n) {
            auto fn = BB->getFirstNode();
            for (auto pred : BB->predcessors()) {
                auto ln = pred->getLastNode();
                if (!ln) {
                    std::string valName;
                    getValueName(n->getValue(), valName);
                    errs() << "WARN: No last node for "
                           << valName << "\n";
                } else {
                    out << "\tNODE" << ln << " -> NODE" << fn
                        << " [style=dotted color=purple]\n";
                }
            }

            for (auto pred : BB->successors()) {
                auto ln = BB->getLastNode();
                auto fn = pred->getFirstNode();
                if (!ln) {
                    std::string valName;
                    getValueName(n->getValue(), valName);
                    errs() << "WARN: No last node for "
                           << valName << "\n";
                } else {
                    out << "\tNODE" << ln << " -> NODE" << fn
                        << " [style=dotted color=red]\n";
                }
            }
        }
    }
#endif // ENABLE_CFG

    if (n->getSubgraph()) {
        out << "\tNODE" << n << " -> NODE" <<  n->getSubgraph()->getEntry()
            << " [style=dashed label=\"call\"]\n";
    }
}

void print_to_dot(LLVMDependenceGraph *dg,
                  bool issubgraph = false,
                  const char *description = NULL)
{
    static unsigned subgraph_no = 0;
    const llvm::Value *val;
    std::string valName;
    std::ostream& out = std::cout;

    if (!dg)
        return;

    if (issubgraph) {
        out << "subgraph \"cluster_" << subgraph_no++;
    } else {
        out << "digraph \""<< description ? description : "DependencyGraph";
    }

    out << "\" {\n";

    for (auto I = dg->begin(), E = dg->end(); I != E; ++I)
    {
        auto n = I->second;
        if (!n) {
                getValueName(dg->getEntry()->getValue(), valName);
                errs() << "WARN [" << valName
                       << "]: Node is NULL for value: "
                       << *I->first << "\n";

            continue;
        }

        val = n->getValue();

        print_to_dot(n->getSubgraph(), true);
        LLVMDependenceGraph *params = n->getParameters();
        if (params) {
            print_to_dot(params, true);

            // add control edge from call-site to the parameters subgraph
            out << "\tNODE" << n << " -> NODE" <<  params->getEntry()
                << "[label=\"params\"]\n";
        }

        getValueName(val, valName);

        out << "\tNODE" << n << " [label=\"" << valName;

#ifdef ENABLE_CFG
        if (OPTIONS.printBB) {
            auto BB = n->getBasicBlock();
            if (!BB) {
                errs() << "WARN: No basic block for " << valName << "\n";
            } else {
                auto fn = BB->getFirstNode();
                if (!fn) {
                    errs() << "CRITICAL: No first value for "
                           << valName << "\n";
                } else {
                auto fval = fn->getValue();
                    if (!fval) {
                        errs() << "WARN: No value in first value for "
                               << valName << "\n";
                    } else {
                        getValueName(fval, valName);
                        out << "\\nBB: " << valName;
                        if (n == fn)
                            out << "\\nBB head (preds "
                                << BB->predcessorsNum() << ")";
                        if (BB->getLastNode() == n)
                            out << "\\nBB tail (succs "
                                << BB->successorsNum() << ")";
                    }
                }
            }
        }
#endif  // ENABLE_CFG

        for (auto d : n->getDefs()) {
            getValueName(d->getValue(), valName);
            out << "\\nDEF " << valName;
        }
        for (auto d : n->getPtrs()) {
            getValueName(d->getValue(), valName);
            out << "\\nPTR " << valName;
        }

        out << "\"];\n";
            //<<" (runid=" << n->getDFSrun() << ")\"];\n";
    }

    for (auto I = dg->begin(), E = dg->end(); I != E; ++I) {
        auto n = I->second;
        if (!n) {
                errs() << "WARN [" << dg
                       << "]: Node is NULL for value: "
                       << *I->first << "\n";

            continue;
        }

        dump_to_dot(I->second, out);
    }

    out << "}\n";
}

int main(int argc, char *argv[])
{
    llvm::LLVMContext context;
    llvm::SMDiagnostic SMD;
    std::unique_ptr<llvm::Module> M;
    const char *module = NULL;

    // default
    OPTIONS.printControlDep = true;
    OPTIONS.printDataDep = true;

    // parse options
    for (int i = 1; i < argc; ++i) {
        if (strcmp(argv[i], "-no-control") == 0) {
            OPTIONS.printControlDep = false;
        } else if (strcmp(argv[i], "-no-data") == 0) {
            OPTIONS.printDataDep = false;

#if ENABLE_CFG
        } else if (strcmp(argv[i], "-bb") == 0) {
            OPTIONS.printBB = true;
        } else if (strcmp(argv[i], "-cfg") == 0) {
            OPTIONS.printCFG = true;
        } else if (strcmp(argv[i], "-cfgall") == 0) {
            OPTIONS.printCFG = true;
            OPTIONS.printRevCFG = true;
#endif // ENABLE_CFG

        } else {
            module = argv[i];
        }
    }

    if (!module) {
        errs() << "Usage: % IR_module [output_file]\n";
        return 1;
    }

    M = llvm::parseIRFile(module, SMD, context);
    if (!M) {
        SMD.print(argv[0], errs());
        return 1;
    }

    LLVMDependenceGraph d;
    d.build(&*M);

    print_to_dot(&d, false, "LLVM Dependence Graph");

    return 0;
}
<commit_msg>llvm-dg-dump: fix it after CFG representation changed<commit_after>#include <assert.h>
#include <cstdio>

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/IRReader/IRReader.h>

#include <iostream>
#include <string>

#include "../src/LLVMDependenceGraph.h"

using namespace dg;
using llvm::errs;

static struct {
#if ENABLE_CFG
    bool printCFG;
    bool printRevCFG;
    bool printBB;
#endif

    bool printControlDep;
    bool printDataDep;
} OPTIONS;

static std::string& getValueName(const llvm::Value *val, std::string &str)
{
    llvm::raw_string_ostream s(str);

    str.clear();

    if (!val) {
        s << "[NULL]";
        return s.str();
    }

    if (llvm::isa<llvm::Function>(val))
        s << "ENTRY " << val->getName();
    else
        s << *val;

    return s.str();
}

static void dump_to_dot(LLVMDGNode *n, std::ostream& out)
{
    const llvm::Value *val;

    /* do not draw multiple edges */
    if (n->getDFSrun() == 1)
        return;
    else
        n->setDFSrun(1);

    if (OPTIONS.printControlDep)
        for (auto I = n->control_begin(), E = n->control_end();
             I != E; ++I)
            out << "\tNODE" << n << " -> NODE" <<  *I << "\n";

    if (OPTIONS.printDataDep)
        for (auto I = n->dependence_begin(), E = n->dependence_end();
             I != E; ++I)
            out << "\tNODE" << n << " -> NODE" <<  *I
                << " [color=red]\n";

#if ENABLE_CFG
    if (OPTIONS.printCFG) {
        if (n->hasSuccessor()) {
            LLVMDGNode *succ = n->getSuccessor();
            if (!succ)
                errs() << "n hasSuccessor NULL!\n";

            out << "\tNODE" << n << " -> NODE" << succ
                << " [style=dotted]\n";
        }
    }

    if (OPTIONS.printRevCFG) {
        if (n->hasPredcessor()) {
            out << "\tNODE" << n << " -> NODE" <<  n->getPredcessor()
                << " [style=dotted color=gray]\n";
        }
    }

    // print edges between blocks
    if (OPTIONS.printCFG) {
        auto BB = n->getBasicBlock();
        // if this is BB header, print the edges
        if (BB && BB->getFirstNode() == n) {
            auto fn = BB->getFirstNode();
            for (auto pred : BB->predcessors()) {
                auto ln = pred->getLastNode();
                if (!ln) {
                    std::string valName;
                    getValueName(n->getValue(), valName);
                    errs() << "WARN: No last node for "
                           << valName << "\n";
                } else {
                    out << "\tNODE" << ln << " -> NODE" << fn
                        << " [style=dotted color=purple]\n";
                }
            }

            for (auto pred : BB->successors()) {
                auto ln = BB->getLastNode();
                auto fn = pred->getFirstNode();
                if (!ln) {
                    std::string valName;
                    getValueName(n->getValue(), valName);
                    errs() << "WARN: No last node for "
                           << valName << "\n";
                } else {
                    out << "\tNODE" << ln << " -> NODE" << fn
                        << " [style=dotted color=red]\n";
                }
            }
        }
    }
#endif // ENABLE_CFG

    if (n->getSubgraph()) {
        out << "\tNODE" << n << " -> NODE" <<  n->getSubgraph()->getEntry()
            << " [style=dashed label=\"call\"]\n";
    }
}

void print_to_dot(LLVMDependenceGraph *dg,
                  bool issubgraph = false,
                  const char *description = NULL)
{
    static unsigned subgraph_no = 0;
    const llvm::Value *val;
    std::string valName;
    std::ostream& out = std::cout;

    if (!dg)
        return;

    if (issubgraph) {
        out << "subgraph \"cluster_" << subgraph_no++;
    } else {
        out << "digraph \""<< description ? description : "DependencyGraph";
    }

    out << "\" {\n";

    for (auto I = dg->begin(), E = dg->end(); I != E; ++I)
    {
        auto n = I->second;
        if (!n) {
                getValueName(dg->getEntry()->getValue(), valName);
                errs() << "WARN [" << valName
                       << "]: Node is NULL for value: "
                       << *I->first << "\n";

            continue;
        }

        val = n->getValue();

        print_to_dot(n->getSubgraph(), true);
        LLVMDependenceGraph *params = n->getParameters();
        if (params) {
            print_to_dot(params, true);

            // add control edge from call-site to the parameters subgraph
            out << "\tNODE" << n << " -> NODE" <<  params->getEntry()
                << "[label=\"params\"]\n";
        }

        getValueName(val, valName);

        out << "\tNODE" << n << " [label=\"" << valName;

#ifdef ENABLE_CFG
        if (OPTIONS.printBB) {
            auto BB = n->getBasicBlock();
            if (!BB) {
                errs() << "WARN: No basic block for " << valName << "\n";
            } else {
                auto fn = BB->getFirstNode();
                if (!fn) {
                    errs() << "CRITICAL: No first value for "
                           << valName << "\n";
                } else {
                auto fval = fn->getValue();
                    if (!fval) {
                        errs() << "WARN: No value in first value for "
                               << valName << "\n";
                    } else {
                        getValueName(fval, valName);
                        out << "\\nBB: " << valName;
                        if (n == fn)
                            out << "\\nBB head (preds "
                                << BB->predcessorsNum() << ")";
                        if (BB->getLastNode() == n)
                            out << "\\nBB tail (succs "
                                << BB->successorsNum() << ")";
                    }
                }
            }
        }
#endif  // ENABLE_CFG

        for (auto d : n->getDefs()) {
            getValueName(d->getValue(), valName);
            out << "\\nDEF " << valName;
        }
        for (auto d : n->getPtrs()) {
            getValueName(d->getValue(), valName);
            out << "\\nPTR " << valName;
        }

        out << "\"];\n";
            //<<" (runid=" << n->getDFSrun() << ")\"];\n";
    }

    for (auto I = dg->begin(), E = dg->end(); I != E; ++I) {
        auto n = I->second;
        if (!n) {
                errs() << "WARN [" << dg
                       << "]: Node is NULL for value: "
                       << *I->first << "\n";

            continue;
        }

        dump_to_dot(I->second, out);
    }

    out << "}\n";
}

int main(int argc, char *argv[])
{
    llvm::LLVMContext context;
    llvm::SMDiagnostic SMD;
    std::unique_ptr<llvm::Module> M;
    const char *module = NULL;

    // default
    OPTIONS.printControlDep = true;
    OPTIONS.printDataDep = true;

    // parse options
    for (int i = 1; i < argc; ++i) {
        if (strcmp(argv[i], "-no-control") == 0) {
            OPTIONS.printControlDep = false;
        } else if (strcmp(argv[i], "-no-data") == 0) {
            OPTIONS.printDataDep = false;

#if ENABLE_CFG
        } else if (strcmp(argv[i], "-bb") == 0) {
            OPTIONS.printBB = true;
        } else if (strcmp(argv[i], "-cfg") == 0) {
            OPTIONS.printCFG = true;
        } else if (strcmp(argv[i], "-cfgall") == 0) {
            OPTIONS.printCFG = true;
            OPTIONS.printRevCFG = true;
#endif // ENABLE_CFG

        } else {
            module = argv[i];
        }
    }

    if (!module) {
        errs() << "Usage: % IR_module [output_file]\n";
        return 1;
    }

    M = llvm::parseIRFile(module, SMD, context);
    if (!M) {
        SMD.print(argv[0], errs());
        return 1;
    }

    LLVMDependenceGraph d;
    d.build(&*M);

    print_to_dot(&d, false, "LLVM Dependence Graph");

    return 0;
}
<|endoftext|>


<commit_before>//===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file This pass attaches synthetic debug info to everything. It can be used
/// to create targeted tests for debug info preservation.
///
//===----------------------------------------------------------------------===//

#include "PassPrinters.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"

using namespace llvm;

namespace {

bool isFunctionSkipped(Function &F) {
  return F.isDeclaration() || !F.hasExactDefinition();
}

bool applyDebugifyMetadata(Module &M,
                           iterator_range<Module::iterator> Functions,
                           StringRef Banner) {
  // Skip modules with debug info.
  if (M.getNamedMetadata("llvm.dbg.cu")) {
    errs() << Banner << "Skipping module with debug info\n";
    return false;
  }

  DIBuilder DIB(M);
  LLVMContext &Ctx = M.getContext();

  // Get a DIType which corresponds to Ty.
  DenseMap<uint64_t, DIType *> TypeCache;
  auto getCachedDIType = [&](Type *Ty) -> DIType * {
    uint64_t Size =
        Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
    DIType *&DTy = TypeCache[Size];
    if (!DTy) {
      std::string Name = "ty" + utostr(Size);
      DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
    }
    return DTy;
  };

  unsigned NextLine = 1;
  unsigned NextVar = 1;
  auto File = DIB.createFile(M.getName(), "/");
  auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File,
                            "debugify", /*isOptimized=*/true, "", 0);

  // Visit each instruction.
  for (Function &F : Functions) {
    if (isFunctionSkipped(F))
      continue;

    auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
    bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
    auto SP =
        DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
                           IsLocalToUnit, /*isDefinition=*/true, NextLine,
                           DINode::FlagZero, /*isOptimized=*/true);
    F.setSubprogram(SP);
    for (BasicBlock &BB : F) {
      // Attach debug locations.
      for (Instruction &I : BB)
        I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));

      // Inserting debug values into EH pads can break IR invariants.
      if (BB.isEHPad())
        continue;

      // Attach debug values.
      for (Instruction &I : BB) {
        // Skip void-valued instructions.
        if (I.getType()->isVoidTy())
          continue;

        // Skip the terminator instruction and any just-inserted intrinsics.
        if (isa<TerminatorInst>(&I) || isa<DbgValueInst>(&I))
          break;

        // Don't insert instructions after a musttail call.
        if (auto *Call = dyn_cast<CallInst>(&I))
          if (Call->isMustTailCall())
            break;

        std::string Name = utostr(NextVar++);
        const DILocation *Loc = I.getDebugLoc().get();
        auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
                                               getCachedDIType(I.getType()),
                                               /*AlwaysPreserve=*/true);
        DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc,
                                    BB.getTerminator());
      }
    }
    DIB.finalizeSubprogram(SP);
  }
  DIB.finalize();

  // Track the number of distinct lines and variables.
  NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
  auto *IntTy = Type::getInt32Ty(Ctx);
  auto addDebugifyOperand = [&](unsigned N) {
    NMD->addOperand(MDNode::get(
        Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
  };
  addDebugifyOperand(NextLine - 1); // Original number of lines.
  addDebugifyOperand(NextVar - 1);  // Original number of variables.
  assert(NMD->getNumOperands() == 2 &&
         "llvm.debugify should have exactly 2 operands!");

  // Claim that this synthetic debug info is valid.
  StringRef DIVersionKey = "Debug Info Version";
  if (!M.getModuleFlag(DIVersionKey))
    M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);

  return true;
}

bool checkDebugifyMetadata(Module &M,
                           iterator_range<Module::iterator> Functions,
                           StringRef NameOfWrappedPass,
                           StringRef Banner,
                           bool Strip) {
  // Skip modules without debugify metadata.
  NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
  if (!NMD) {
    errs() << Banner << "Skipping module without debugify metadata\n";
    return false;
  }

  auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
    return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
        ->getZExtValue();
  };
  assert(NMD->getNumOperands() == 2 &&
         "llvm.debugify should have exactly 2 operands!");
  unsigned OriginalNumLines = getDebugifyOperand(0);
  unsigned OriginalNumVars = getDebugifyOperand(1);
  bool HasErrors = false;

  BitVector MissingLines{OriginalNumLines, true};
  BitVector MissingVars{OriginalNumVars, true};
  for (Function &F : Functions) {
    if (isFunctionSkipped(F))
      continue;

    // Find missing lines.
    for (Instruction &I : instructions(F)) {
      if (isa<DbgValueInst>(&I))
        continue;

      auto DL = I.getDebugLoc();
      if (DL && DL.getLine() != 0) {
        MissingLines.reset(DL.getLine() - 1);
        continue;
      }

      errs() << "ERROR: Instruction with empty DebugLoc in function ";
      errs() << F.getName() << " --";
      I.print(errs());
      errs() << "\n";
      HasErrors = true;
    }

    // Find missing variables.
    for (Instruction &I : instructions(F)) {
      auto *DVI = dyn_cast<DbgValueInst>(&I);
      if (!DVI)
        continue;

      unsigned Var = ~0U;
      (void)to_integer(DVI->getVariable()->getName(), Var, 10);
      assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
      MissingVars.reset(Var - 1);
    }
  }

  // Print the results.
  for (unsigned Idx : MissingLines.set_bits())
    errs() << "WARNING: Missing line " << Idx + 1 << "\n";

  for (unsigned Idx : MissingVars.set_bits())
    errs() << "ERROR: Missing variable " << Idx + 1 << "\n";
  HasErrors |= MissingVars.count() > 0;

  errs() << Banner;
  if (!NameOfWrappedPass.empty())
    errs() << " [" << NameOfWrappedPass << "]";
  errs() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
  if (HasErrors) {
    errs() << "Module IR Dump\n";
    M.print(errs(), nullptr, false);
  }

  // Strip the Debugify Metadata if required.
  if (Strip) {
    StripDebugInfo(M);
    M.eraseNamedMetadata(NMD);
    return true;
  }

  return false;
}

/// ModulePass for attaching synthetic debug info to everything, used with the
/// legacy module pass manager.
struct DebugifyModulePass : public ModulePass {
  bool runOnModule(Module &M) override {
    return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
  }

  DebugifyModulePass() : ModulePass(ID) {}

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesAll();
  }

  static char ID; // Pass identification.
};

/// FunctionPass for attaching synthetic debug info to instructions within a
/// single function, used with the legacy module pass manager.
struct DebugifyFunctionPass : public FunctionPass {
  bool runOnFunction(Function &F) override {
    Module &M = *F.getParent();
    auto FuncIt = F.getIterator();
    return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
                     "FunctionDebugify: ");
  }

  DebugifyFunctionPass() : FunctionPass(ID) {}

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesAll();
  }

  static char ID; // Pass identification.
};

/// ModulePass for checking debug info inserted by -debugify, used with the
/// legacy module pass manager.
struct CheckDebugifyModulePass : public ModulePass {
  bool runOnModule(Module &M) override {
    return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
                                 "CheckModuleDebugify", Strip);
  }

  CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "")
      : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}

  static char ID; // Pass identification.

private:
  bool Strip;
  StringRef NameOfWrappedPass;
};

/// FunctionPass for checking debug info inserted by -debugify-function, used
/// with the legacy module pass manager.
struct CheckDebugifyFunctionPass : public FunctionPass {
  bool runOnFunction(Function &F) override {
    Module &M = *F.getParent();
    auto FuncIt = F.getIterator();
    return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
                                 NameOfWrappedPass, "CheckFunctionDebugify",
                                 Strip);
  }

  CheckDebugifyFunctionPass(bool Strip = false,
                            StringRef NameOfWrappedPass = "")
      : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesAll();
  }

  static char ID; // Pass identification.

private:
  bool Strip;
  StringRef NameOfWrappedPass;
};

} // end anonymous namespace

ModulePass *createDebugifyModulePass() {
  return new DebugifyModulePass();
}

FunctionPass *createDebugifyFunctionPass() {
  return new DebugifyFunctionPass();
}

PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
  applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
  return PreservedAnalyses::all();
}

ModulePass *createCheckDebugifyModulePass(bool Strip, StringRef NameOfWrappedPass) {
  return new CheckDebugifyModulePass(Strip, NameOfWrappedPass);
}

FunctionPass *createCheckDebugifyFunctionPass(bool Strip, StringRef NameOfWrappedPass) {
  return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass);
}

PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
                                              ModuleAnalysisManager &) {
  checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false);
  return PreservedAnalyses::all();
}

char DebugifyModulePass::ID = 0;
static RegisterPass<DebugifyModulePass> DM("debugify",
                                    "Attach debug info to everything");

char CheckDebugifyModulePass::ID = 0;
static RegisterPass<CheckDebugifyModulePass> CDM("check-debugify",
                                         "Check debug info from -debugify");

char DebugifyFunctionPass::ID = 0;
static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
                                    "Attach debug info to a function");

char CheckDebugifyFunctionPass::ID = 0;
static RegisterPass<CheckDebugifyFunctionPass> CDF("check-debugify-function",
                                         "Check debug info from -debugify-function");
<commit_msg>Reformat overflowing lines, NFC<commit_after>//===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file This pass attaches synthetic debug info to everything. It can be used
/// to create targeted tests for debug info preservation.
///
//===----------------------------------------------------------------------===//

#include "PassPrinters.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"

using namespace llvm;

namespace {

bool isFunctionSkipped(Function &F) {
  return F.isDeclaration() || !F.hasExactDefinition();
}

bool applyDebugifyMetadata(Module &M,
                           iterator_range<Module::iterator> Functions,
                           StringRef Banner) {
  // Skip modules with debug info.
  if (M.getNamedMetadata("llvm.dbg.cu")) {
    errs() << Banner << "Skipping module with debug info\n";
    return false;
  }

  DIBuilder DIB(M);
  LLVMContext &Ctx = M.getContext();

  // Get a DIType which corresponds to Ty.
  DenseMap<uint64_t, DIType *> TypeCache;
  auto getCachedDIType = [&](Type *Ty) -> DIType * {
    uint64_t Size =
        Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
    DIType *&DTy = TypeCache[Size];
    if (!DTy) {
      std::string Name = "ty" + utostr(Size);
      DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
    }
    return DTy;
  };

  unsigned NextLine = 1;
  unsigned NextVar = 1;
  auto File = DIB.createFile(M.getName(), "/");
  auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File,
                            "debugify", /*isOptimized=*/true, "", 0);

  // Visit each instruction.
  for (Function &F : Functions) {
    if (isFunctionSkipped(F))
      continue;

    auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
    bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
    auto SP =
        DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
                           IsLocalToUnit, /*isDefinition=*/true, NextLine,
                           DINode::FlagZero, /*isOptimized=*/true);
    F.setSubprogram(SP);
    for (BasicBlock &BB : F) {
      // Attach debug locations.
      for (Instruction &I : BB)
        I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));

      // Inserting debug values into EH pads can break IR invariants.
      if (BB.isEHPad())
        continue;

      // Attach debug values.
      for (Instruction &I : BB) {
        // Skip void-valued instructions.
        if (I.getType()->isVoidTy())
          continue;

        // Skip the terminator instruction and any just-inserted intrinsics.
        if (isa<TerminatorInst>(&I) || isa<DbgValueInst>(&I))
          break;

        // Don't insert instructions after a musttail call.
        if (auto *Call = dyn_cast<CallInst>(&I))
          if (Call->isMustTailCall())
            break;

        std::string Name = utostr(NextVar++);
        const DILocation *Loc = I.getDebugLoc().get();
        auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
                                               getCachedDIType(I.getType()),
                                               /*AlwaysPreserve=*/true);
        DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc,
                                    BB.getTerminator());
      }
    }
    DIB.finalizeSubprogram(SP);
  }
  DIB.finalize();

  // Track the number of distinct lines and variables.
  NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
  auto *IntTy = Type::getInt32Ty(Ctx);
  auto addDebugifyOperand = [&](unsigned N) {
    NMD->addOperand(MDNode::get(
        Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
  };
  addDebugifyOperand(NextLine - 1); // Original number of lines.
  addDebugifyOperand(NextVar - 1);  // Original number of variables.
  assert(NMD->getNumOperands() == 2 &&
         "llvm.debugify should have exactly 2 operands!");

  // Claim that this synthetic debug info is valid.
  StringRef DIVersionKey = "Debug Info Version";
  if (!M.getModuleFlag(DIVersionKey))
    M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);

  return true;
}

bool checkDebugifyMetadata(Module &M,
                           iterator_range<Module::iterator> Functions,
                           StringRef NameOfWrappedPass,
                           StringRef Banner,
                           bool Strip) {
  // Skip modules without debugify metadata.
  NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
  if (!NMD) {
    errs() << Banner << "Skipping module without debugify metadata\n";
    return false;
  }

  auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
    return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
        ->getZExtValue();
  };
  assert(NMD->getNumOperands() == 2 &&
         "llvm.debugify should have exactly 2 operands!");
  unsigned OriginalNumLines = getDebugifyOperand(0);
  unsigned OriginalNumVars = getDebugifyOperand(1);
  bool HasErrors = false;

  BitVector MissingLines{OriginalNumLines, true};
  BitVector MissingVars{OriginalNumVars, true};
  for (Function &F : Functions) {
    if (isFunctionSkipped(F))
      continue;

    // Find missing lines.
    for (Instruction &I : instructions(F)) {
      if (isa<DbgValueInst>(&I))
        continue;

      auto DL = I.getDebugLoc();
      if (DL && DL.getLine() != 0) {
        MissingLines.reset(DL.getLine() - 1);
        continue;
      }

      errs() << "ERROR: Instruction with empty DebugLoc in function ";
      errs() << F.getName() << " --";
      I.print(errs());
      errs() << "\n";
      HasErrors = true;
    }

    // Find missing variables.
    for (Instruction &I : instructions(F)) {
      auto *DVI = dyn_cast<DbgValueInst>(&I);
      if (!DVI)
        continue;

      unsigned Var = ~0U;
      (void)to_integer(DVI->getVariable()->getName(), Var, 10);
      assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
      MissingVars.reset(Var - 1);
    }
  }

  // Print the results.
  for (unsigned Idx : MissingLines.set_bits())
    errs() << "WARNING: Missing line " << Idx + 1 << "\n";

  for (unsigned Idx : MissingVars.set_bits())
    errs() << "ERROR: Missing variable " << Idx + 1 << "\n";
  HasErrors |= MissingVars.count() > 0;

  errs() << Banner;
  if (!NameOfWrappedPass.empty())
    errs() << " [" << NameOfWrappedPass << "]";
  errs() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
  if (HasErrors) {
    errs() << "Module IR Dump\n";
    M.print(errs(), nullptr, false);
  }

  // Strip the Debugify Metadata if required.
  if (Strip) {
    StripDebugInfo(M);
    M.eraseNamedMetadata(NMD);
    return true;
  }

  return false;
}

/// ModulePass for attaching synthetic debug info to everything, used with the
/// legacy module pass manager.
struct DebugifyModulePass : public ModulePass {
  bool runOnModule(Module &M) override {
    return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
  }

  DebugifyModulePass() : ModulePass(ID) {}

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesAll();
  }

  static char ID; // Pass identification.
};

/// FunctionPass for attaching synthetic debug info to instructions within a
/// single function, used with the legacy module pass manager.
struct DebugifyFunctionPass : public FunctionPass {
  bool runOnFunction(Function &F) override {
    Module &M = *F.getParent();
    auto FuncIt = F.getIterator();
    return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
                     "FunctionDebugify: ");
  }

  DebugifyFunctionPass() : FunctionPass(ID) {}

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesAll();
  }

  static char ID; // Pass identification.
};

/// ModulePass for checking debug info inserted by -debugify, used with the
/// legacy module pass manager.
struct CheckDebugifyModulePass : public ModulePass {
  bool runOnModule(Module &M) override {
    return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
                                 "CheckModuleDebugify", Strip);
  }

  CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "")
      : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}

  static char ID; // Pass identification.

private:
  bool Strip;
  StringRef NameOfWrappedPass;
};

/// FunctionPass for checking debug info inserted by -debugify-function, used
/// with the legacy module pass manager.
struct CheckDebugifyFunctionPass : public FunctionPass {
  bool runOnFunction(Function &F) override {
    Module &M = *F.getParent();
    auto FuncIt = F.getIterator();
    return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
                                 NameOfWrappedPass, "CheckFunctionDebugify",
                                 Strip);
  }

  CheckDebugifyFunctionPass(bool Strip = false,
                            StringRef NameOfWrappedPass = "")
      : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesAll();
  }

  static char ID; // Pass identification.

private:
  bool Strip;
  StringRef NameOfWrappedPass;
};

} // end anonymous namespace

ModulePass *createDebugifyModulePass() {
  return new DebugifyModulePass();
}

FunctionPass *createDebugifyFunctionPass() {
  return new DebugifyFunctionPass();
}

PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
  applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
  return PreservedAnalyses::all();
}

ModulePass *createCheckDebugifyModulePass(bool Strip,
                                          StringRef NameOfWrappedPass) {
  return new CheckDebugifyModulePass(Strip, NameOfWrappedPass);
}

FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
                                              StringRef NameOfWrappedPass) {
  return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass);
}

PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
                                              ModuleAnalysisManager &) {
  checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false);
  return PreservedAnalyses::all();
}

char DebugifyModulePass::ID = 0;
static RegisterPass<DebugifyModulePass> DM("debugify",
                                           "Attach debug info to everything");

char CheckDebugifyModulePass::ID = 0;
static RegisterPass<CheckDebugifyModulePass>
    CDM("check-debugify", "Check debug info from -debugify");

char DebugifyFunctionPass::ID = 0;
static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
                                             "Attach debug info to a function");

char CheckDebugifyFunctionPass::ID = 0;
static RegisterPass<CheckDebugifyFunctionPass>
    CDF("check-debugify-function", "Check debug info from -debugify-function");
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <map>
#include <cstdarg>
#include <exception>

using namespace std;

class MethodNotFoundException { //: public exception {
 private:
  string arg;
 public:
  MethodNotFoundException(string arg = "") : arg(arg) { }
  ~MethodNotFoundException() { }
  virtual const char* what() const throw() {
    return (string("abc ") + arg).c_str();
  }
};

class _Str;
class _Role;
class _ClassHOW;
class _Hash;

class P6opaque {
 private:
  map<string, P6opaque*> properties;
  const std::string &_class;

 protected:

 public:
  /* Constructors */
  P6opaque(const std::string& _class) :
      _class(_class) { }

  /* methods */
  P6opaque* dispatch(std::string arg) {
    P6opaque* result = properties[arg];
    if (result) {
      return result;
    }
    else {
      throw MethodNotFoundException(arg);
    }
  }

  const std::string& get_class() {
    return _class;
  }

  P6opaque* get_attr(std::string attr_name) {
    return properties[attr_name];
  }

  void set_attr(std::string attr_name, P6opaque* attr) {
    properties[attr_name] = attr;
  }

//  const P6opaque& getHOW();
//  static const P6opaque& getHOW();
};

class _Mu : public P6opaque {
 private:
  /* Attributes */
  static P6opaque* HOW;

 public:
  /* Constructors */
  _Mu(string arg = "Mu()") :
      P6opaque(arg) {
  }

  /* Some general methods */
  //bool does(_Role* role);
  //bool can(_Role* role);
  _Str* Str();

  virtual P6opaque* create() {
    return new _Mu();
  }

  static P6opaque* _new(_Hash* args) {
    P6opaque* candidate = _Mu::_CREATE("P6opaque");
    return result->_bless(args);
  }

  virtual P6opaque& get_HOW() {
    return _Mu::_get_HOW();
  }

  static P6opaque& _get_HOW();

  static void _BUILD();
  static P6opaque* _CREATE() {
    return new P6opaque();
  }

  static P6opaque* _CREATE(string repr) {
    if ("*" == repr) {
      return new P6opaque("Mu()");
    }
  }

  virtual P6opaque* _bless(_Hash* hash) {
    //call CREATE
    _Mu* result = _new();
    _Hash::iterator it;
    for (it = _Hash.begin(); it != _Hash.end(); it++) {

    }

  }
};

class _Any : public _Mu {
 public:
  _Any(string arg = "Any()") :
      _Mu(arg) {
  }
};

/*

class _Role : public _Any {
 public:
  _Role(string arg = "Role()") :
      _Any(arg) {
  }
};

*/

/*
class _Iterable : public _Any {
 public:
  _Iterable(string arg = "Iterable()") :
};
*/

/*

class _Str : public _Any {
 private:
  std::string& value;

 public:
  _Str() : _Mu("Str()") {
  }

  _Str(std::string value) :
      _Mu("Str()"), value(value) {
  }

  string& str() {
    return value;
  }
};

class _Int : public _Any {
 private:
  long long value;

 public:
  _Int() :
      _Mu("Int()") {
  }

  _Int(long long value) :
      _Mu("Int()"), value(value) {
  }
}; */

/*
class _Num : public _Any {
};

*/

class _ClassHOW : public _Mu {
 public:
  _ClassHOW(string arg="ClassHOW()") : _Mu(arg) { }
};

/*
class _RoleHOW : public _Mu {
};

class _GrammarHOw : public _Mu {
};

class _Grammar : public _Mu {
};
*/

class _Bool : public _Any {
 private:
  bool value;
 public:

};

/*
_Role _Code = _Role::create("Code()",
      new map<string, P6opaque*>("string", )
    );
*/

/* role Code */
/*
class _Code : public _Any {
};

class _Block : public _Any {
};

class _Parcel : public _Any {
};

enum _Routine_t {
  _Sub,
  _Method,
  _Submethod,
  _Macro,
};

class _Routine : public _Code {

};

class _Hash : _Any {
};

*/

_Mu* _say(int num_args, ...) {
  _Mu* val;
  va_list vl;
  va_start(vl,num_args);

  for (i = 0; i < num_args; i++) {
    cout << val->Str().str();
  }

  cout << "\n";

  return new Mu;
}

int main() {
  try {
    P6opaque *a = new _Any();
    P6opaque *instance = a->_new();
    say(1, instance);
    //P6opaque *b = a->dispatch(".^methods"); // .^methods should return an Array of methods.
    //cout << b->dispatch(".WHAT"); // .WHAT returns a Str which says "Array()".
    //cout << b;
  }
  catch (MethodNotFoundException e) {
    cerr << "MethodNotFoundException: " << e.getErr() << endl;
  }
  catch (...) {
    cerr << "Uncaught exception" << endl;
    return -1;
  }
  return 0;
}

_Str* _Mu::Str() {
  return new _Str("Mu()");
}

P6opague& _Mu::getHOW() {
  return
}

static P6opaque& _Mu::_get_HOW() {
  if (HOW == NULL) {
    HOW = new _ClassHOW();
  }

  return *HOW;
}

<commit_msg>So... HOW's should be per instance, not static, they may reference the same object, but thats not required, hmm... more to do...<commit_after>#include <iostream>
#include <string>
#include <map>
#include <cstdarg>
#include <exception>

using namespace std;

class MethodNotFoundException { //: public exception {
 private:
  string arg;
 public:
  MethodNotFoundException(string arg = "") : arg(arg) { }
  ~MethodNotFoundException() { }
  virtual const char* what() const throw() {
    return (string("abc ") + arg).c_str();
  }
};

class _Str;
class _Role;
class _ClassHOW;
class _Hash;

class P6opaque {
 private:
  map<string, P6opaque*> properties;
  const std::string &_class;

 protected:

 public:
  /* Constructors */
  P6opaque(const std::string& _class) :
      _class(_class) { }

  /* methods */
  P6opaque* dispatch(std::string arg) {
    P6opaque* result = properties[arg];
    if (result) {
      return result;
    }
    else {
      throw MethodNotFoundException(arg);
    }
  }

  const std::string& get_class() {
    return _class;
  }

  P6opaque* get_attr(std::string attr_name) {
    return properties[attr_name];
  }

  void set_attr(std::string attr_name, P6opaque* attr) {
    properties[attr_name] = attr;
  }

  virtual P6opaque* _bless(_Hash* hash) = 0;
};

class _Mu : public P6opaque {
 protected:
  /* Attributes */
  _Mu* HOW;

 public:
  /* Constructors */
  _Mu(string arg = "Mu()") :
      P6opaque(arg) {
  }

  /* Some general methods */
  _Str* Str();

  virtual P6opaque* create() {
    return new _Mu();
  }

  static P6opaque* _new(_Hash* args = NULL) {
    P6opaque* candidate = _Mu::_CREATE("*");
    return candidate->_bless(args);
  }

  virtual P6opaque& get_HOW() {
    return *HOW;
  }

  virtual void _BUILD();
  virtual P6opaque* _CREATE() {

    return new _Mu();
  }

  static P6opaque* _CREATE(string repr) {
    if ("*" == repr) {
      return new _Mu("Mu()");
    }
    return NULL;
  }

  static P6opaque* _CREATE(_Str* repr);

  virtual P6opaque* _bless(_Hash* hash) {
    // BUILDALL
    return this;
  }
};

_Mu* _GLOBAL_Mu = new _Mu;

/* do i want a kernel object?
class _Kernel : public _Mu {
 private:
 public:
  _Kernel(string name="Kernel()");
};

_Mu* _GKernel = new _Kernel();
*/

class _Any : public _Mu {
 public:
  _Any(string arg = "Any()") :
      _Mu(arg) {
  }
};

_Mu* _GLOBAL_Any = new _Any();

class _Whatever : public _Any {
 private:
  _Mu* HOW;
 public:

};

_Mu* _GLOBAL_Whatever = new _Whatever();

/*

class _Role : public _Any {
 public:
  _Role(string arg = "Role()") :
      _Any(arg) {
  }
};

*/

/*
class _Iterable : public _Any {
 public:
  _Iterable(string arg = "Iterable()") :
};
*/

class _Str : public _Any {
 private:
  std::string* value;
  static _Mu* HOW;

 public:
  _Str(string arg = "Str()") : _Any(arg) {
  }

  _Str(string arg = "Str()", std::string value = "Str()") :
      _Any(arg), value(new string(value)) {
  }

  ~_Str() {
    delete value;
  }

  static _Str* create(string value) {
    return new _Str("Str()", value);
  }

  string& str() {
    return *value;
  }
};

/*
class _Int : public _Any {
 private:
  long long value;

 public:
  _Int() :
      _Mu("Int()") {
  }

  _Int(long long value) :
      _Mu("Int()"), value(value) {
  }
}; */

/*
class _Num : public _Any {
};

*/

class _ClassHOW : public _Mu {
 public:
  _ClassHOW(string arg="ClassHOW()") : _Mu(arg) { }
};

/*
class _RoleHOW : public _Mu {
};

class _GrammarHOw : public _Mu {
};

class _Grammar : public _Mu {
};
*/

//class _Bool : public _Any {
// private:
//  bool value;
// public:
//
//};

/*
_Role _Code = _Role::create("Code()",
      new map<string, P6opaque*>("string", )
    );
*/

/* role Code */
/*
class _Code : public _Any {
};

class _Block : public _Any {
};

class _Parcel : public _Any {
};

enum _Routine_t {
  _Sub,
  _Method,
  _Submethod,
  _Macro,
};

class _Routine : public _Code {

};

class _Hash : _Any {
};

*/

_Mu* _say(int num_args, ...) {
  _Mu* val;
  va_list vl;
  va_start(vl, num_args);

  for (int i = 0; i < num_args; i++) {
    cout << val->Str()->str();
  }

  cout << "\n";

  return new _Mu;
}

int main() {
  try {
    P6opaque *instance = _GLOBAL_Any->_new();
    _say(1, instance);
    //P6opaque *b = a->dispatch(".^methods"); // .^methods should return an Array of methods.
    //cout << b->dispatch(".WHAT"); // .WHAT returns a Str which says "Array()".
    //cout << b;
  }
  catch (MethodNotFoundException e) {
    cerr << "MethodNotFoundException: " << e.what() << endl;
  }
  catch (...) {
    cerr << "Uncaught exception" << endl;
    return -1;
  }
  return 0;
}

_Str* _Mu::Str() {
  return _Str::create("Mu()");
}

P6opaque* _Mu::_CREATE(_Str* repr) {
  return _Mu::_CREATE(repr->str());
}

//P6opaque& _Mu::getHOW() {
//}

// P6opaque& _Mu::_get_HOW() {
//  if (HOW == NULL) {
//    HOW = new _ClassHOW();
//  }
//
//  return *HOW;
//}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rc.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 00:59:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#define _TOOLS_RC_CXX

#include <string.h>

#ifndef _DATE_HXX
#include <date.hxx>
#endif
#ifndef _TIME_HXX
#include <time.hxx>
#endif

#ifndef _TOOLS_RC_HXX
#include <rc.hxx>
#endif
#ifndef _TOOLS_RCID_H
#include <rcid.h>
#endif

// =======================================================================

Resource::Resource( const ResId& rResId )
{
    GetRes( rResId.SetRT( RSC_RESOURCE ) );
}

// -----------------------------------------------------------------------

void Resource::GetRes( const ResId& rResId )
{
    if ( rResId.GetResMgr() )
        rResId.GetResMgr()->GetResource( rResId, this );
    else
        GetResManager()->GetResource( rResId, this );

    IncrementRes( sizeof( RSHEADER_TYPE ) );
}

// -----------------------------------------------------------------------

// =======================================================================

Time::Time( const ResId& rResId )
{
    nTime = 0;
    rResId.SetRT( RSC_TIME );
    ResMgr* pResMgr = NULL;

    ResMgr::GetResourceSkipHeader( rResId, &pResMgr );

    ULONG nObjMask = (USHORT)pResMgr->ReadLong();

    if ( 0x01 & nObjMask )
        SetHour( (USHORT)pResMgr->ReadShort() );
    if ( 0x02 & nObjMask )
        SetMin( (USHORT)pResMgr->ReadShort() );
    if ( 0x04 & nObjMask )
        SetSec( (USHORT)pResMgr->ReadShort() );
    if ( 0x08 & nObjMask )
        Set100Sec( (USHORT)pResMgr->ReadShort() );
}

// =======================================================================

Date::Date( const ResId& rResId )
{
    rResId.SetRT( RSC_DATE );
    ResMgr* pResMgr = NULL;

    ResMgr::GetResourceSkipHeader( rResId, &pResMgr );

    ULONG nObjMask = (USHORT)pResMgr->ReadLong();

    if ( 0x01 & nObjMask )
        SetYear( (USHORT)pResMgr->ReadShort() );
    if ( 0x02 & nObjMask )
        SetMonth( (USHORT)pResMgr->ReadShort() );
    if ( 0x04 & nObjMask )
        SetDay( (USHORT)pResMgr->ReadShort() );
}
<commit_msg>INTEGRATION: CWS residcleanup (1.8.64); FILE MERGED 2007/02/18 16:55:59 pl 1.8.64.1: #i74635# get rid of implicit global ResMgr<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rc.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-26 09:47:56 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#define _TOOLS_RC_CXX

#include <string.h>

#ifndef _DATE_HXX
#include <date.hxx>
#endif
#ifndef _TIME_HXX
#include <time.hxx>
#endif

#ifndef _TOOLS_RC_HXX
#include <rc.hxx>
#endif
#ifndef _TOOLS_RCID_H
#include <rcid.h>
#endif

// =======================================================================

Resource::Resource( const ResId& rResId )
{
    GetRes( rResId.SetRT( RSC_RESOURCE ) );
}

// -----------------------------------------------------------------------

void Resource::GetRes( const ResId& rResId )
{
    if( rResId.GetResMgr() )
        m_pResMgr = rResId.GetResMgr();
    m_pResMgr->GetResource( rResId, this );
    IncrementRes( sizeof( RSHEADER_TYPE ) );
}

// -----------------------------------------------------------------------

// =======================================================================

Time::Time( const ResId& rResId )
{
    nTime = 0;
    rResId.SetRT( RSC_TIME );
    ResMgr* pResMgr = NULL;

    ResMgr::GetResourceSkipHeader( rResId, &pResMgr );

    ULONG nObjMask = (USHORT)pResMgr->ReadLong();

    if ( 0x01 & nObjMask )
        SetHour( (USHORT)pResMgr->ReadShort() );
    if ( 0x02 & nObjMask )
        SetMin( (USHORT)pResMgr->ReadShort() );
    if ( 0x04 & nObjMask )
        SetSec( (USHORT)pResMgr->ReadShort() );
    if ( 0x08 & nObjMask )
        Set100Sec( (USHORT)pResMgr->ReadShort() );
}

// =======================================================================

Date::Date( const ResId& rResId )
{
    rResId.SetRT( RSC_DATE );
    ResMgr* pResMgr = NULL;

    ResMgr::GetResourceSkipHeader( rResId, &pResMgr );

    ULONG nObjMask = (USHORT)pResMgr->ReadLong();

    if ( 0x01 & nObjMask )
        SetYear( (USHORT)pResMgr->ReadShort() );
    if ( 0x02 & nObjMask )
        SetMonth( (USHORT)pResMgr->ReadShort() );
    if ( 0x04 & nObjMask )
        SetDay( (USHORT)pResMgr->ReadShort() );
}
<|endoftext|>


<commit_before>#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "msg_filter.hpp"

using wissbi::MsgBuf;
using wissbi::MsgFilter;
using ::testing::_;
using ::testing::Return;

class MockInputPolicy {
    public:
    MOCK_METHOD1(Get, bool(MsgBuf *msg_buf));
    MOCK_METHOD1(Put, bool(const MsgBuf &msg_buf));
};

class MockOutputPolicy {
    public:
    MOCK_METHOD1(Get, bool(MsgBuf *msg_buf));
    MOCK_METHOD1(Put, bool(const MsgBuf &msg_buf));
};

class MsgFilterTest : public ::testing::Test {
    protected:
    virtual void SetUp() {
    }

    virtual void TearDown() {
    }
};

TEST_F(MsgFilterTest, ReadFail) {
    MsgFilter<MockInputPolicy, MockOutputPolicy> filter;
    EXPECT_CALL(static_cast<MockInputPolicy&>(filter), Get(_)).WillOnce(Return(false));
    EXPECT_CALL(static_cast<MockOutputPolicy&>(filter), Put(_)).Times(0);
    EXPECT_FALSE(filter.Filter());
}

<commit_msg>add filter loop test<commit_after>#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "msg_filter.hpp"

using wissbi::MsgBuf;
using wissbi::MsgFilter;
using ::testing::_;
using ::testing::Return;
using namespace std;

class MockInputPolicy {
    public:
    MOCK_METHOD1(Get, bool(MsgBuf *msg_buf));
    MOCK_METHOD1(Put, bool(const MsgBuf &msg_buf));
};

class MockOutputPolicy {
    public:
    MOCK_METHOD1(Get, bool(MsgBuf *msg_buf));
    MOCK_METHOD1(Put, bool(const MsgBuf &msg_buf));
};

class MsgFilterTest : public ::testing::Test {
    protected:
    virtual void SetUp() {
    }

    virtual void TearDown() {
    }
};

TEST_F(MsgFilterTest, ReadFail) {
    MsgFilter<MockInputPolicy, MockOutputPolicy> filter;
    EXPECT_CALL(static_cast<MockInputPolicy&>(filter), Get(_)).WillOnce(Return(false));
    EXPECT_CALL(static_cast<MockOutputPolicy&>(filter), Put(_)).Times(0);
    EXPECT_FALSE(filter.Filter());
}

TEST_F(MsgFilterTest, Filter) {
    MsgFilter<MockInputPolicy, MockOutputPolicy> filter;
    MsgBuf *buf_ptr;
    EXPECT_CALL(static_cast<MockInputPolicy&>(filter), Get(_)).WillOnce(Return(true));
    EXPECT_CALL(static_cast<MockOutputPolicy&>(filter), Put(_)).WillOnce(Return(true));
    filter.Filter();
}

TEST_F(MsgFilterTest, FilterLoop) {
    MsgFilter<MockInputPolicy, MockOutputPolicy> filter;
    MsgBuf *buf_ptr;
    EXPECT_CALL(static_cast<MockInputPolicy&>(filter), Get(_)).Times(4)
        .WillOnce(Return(true)).WillOnce(Return(true)).WillOnce(Return(true)).WillRepeatedly(Return(false));
    EXPECT_CALL(static_cast<MockOutputPolicy&>(filter), Put(_)).Times(3).WillRepeatedly(Return(true));
    filter.FilterLoop();
}

<|endoftext|>


<commit_before>#include "nanocv.h"
#include "common/dot.hpp"
#include "common/mad.hpp"

using namespace ncv;

ncv::thread_pool_t pool;

typedef double test_scalar_t;
typedef ncv::tensor::vector_types_t<test_scalar_t>::tvector     test_vector_t;
typedef ncv::tensor::vector_types_t<test_scalar_t>::tvectors    test_vectors_t;

template
<
        typename tscalar,
        typename tsize
>
tscalar dot_eig(const tscalar* vec1, const tscalar* vec2, tsize size)
{
        return tensor::make_vector(vec1, size).dot(tensor::make_vector(vec2, size));
}

template
<
        typename tscalar,
        typename tsize
>
void mad_eig(const tscalar* idata, tscalar weight, tsize size, tscalar* odata)
{
        tensor::make_vector(odata, size).array() += weight * tensor::make_vector(idata, size).array();
}

template
<
        typename tvector
>
void rand_vector(size_t size, tvector& vector)
{
        vector.resize(size);
        vector.setRandom();
}

template
<
        typename tvector
>
void zero_vector(tvector& vector)
{
        vector.setZero();
}

template
<
        typename top,
        typename tvector,
        typename tscalar = typename tvector::Scalar
>
tscalar test_dot(
        top op, const char* name, size_t n_tests,
        const tvector& vec1, const tvector& vec2)
{
        const ncv::timer_t timer;

        // run multiple tests
        tscalar ret = 0;
        for (size_t t = 0; t < n_tests; t ++)
        {
                ret += op(vec1.data(), vec2.data(), vec1.size());
        }

        const size_t milis = static_cast<size_t>(timer.miliseconds());
        std::cout << name << "= " << text::resize(text::to_string(milis), 4, align::right) << "ms  ";

        return ret;
}

template
<
        typename top,
        typename tvector,
        typename tscalar = typename tvector::Scalar
>
tscalar test_mad(
        top op, const char* name, size_t n_tests,
        const tvector& vec1, const tvector& vec2, tscalar wei)
{
        vector_t cvec1 = vec1;
        vector_t cvec2 = vec2;

        const ncv::timer_t timer;

        // run multiple tests
        for (size_t t = 0; t < n_tests; t ++)
        {
                op(cvec1.data(), wei, cvec1.size(), cvec2.data());
        }

        const size_t milis = static_cast<size_t>(timer.miliseconds());
        std::cout << name << "= " << text::resize(text::to_string(milis), 4, align::right) << "ms  ";

        return cvec2.sum();
}

template
<
        typename tscalar
>
void check(tscalar result, tscalar baseline, const char* name)
{
        const tscalar err = std::fabs(result - baseline);

        if (!math::almost_equal(err, tscalar(0)))
        {
                std::cout << name << " FAILED (diff = " << err << ")!" << std::endl;
        }
}

void test_dot(size_t size, size_t n_tests)
{
        test_vector_t vec1, vec2;

        rand_vector(size, vec1);
        rand_vector(size, vec2);

        const string_t header = (boost::format("(%1%x%2%): ") % size % n_tests).str();
        std::cout << text::resize(header, 16);

        typedef decltype(vec1.size()) test_size_t;

        const test_scalar_t dot    = test_dot(ncv::dot<test_scalar_t, test_size_t>, "dot", n_tests, vec1, vec2);
        const test_scalar_t dotul4 = test_dot(ncv::dot_unroll4<test_scalar_t, test_size_t>, "dotul4", n_tests, vec1, vec2);
        const test_scalar_t dotul8 = test_dot(ncv::dot_unroll8<test_scalar_t, test_size_t>, "dotul8", n_tests, vec1, vec2);
        const test_scalar_t doteig = test_dot(dot_eig<test_scalar_t, test_size_t>, "doteig", n_tests, vec1, vec2);
        std::cout << std::endl;

        check(dot,      dot, "dot");
        check(dotul4,   dot, "dotul4");
        check(dotul8,   dot, "dotul8");
        check(doteig,   dot, "doteig");
}

void test_mad(size_t size, size_t n_tests)
{
        test_vector_t vec1, vec2;

        rand_vector(size, vec1);
        rand_vector(size, vec2);

        test_scalar_t wei;

        wei = vec1(0) + vec2(3);

        const string_t header = (boost::format("(%1%x%2%): ") % size % n_tests).str();
        std::cout << text::resize(header, 16);

        typedef decltype(vec1.size()) test_size_t;

        const test_scalar_t mad    = test_mad(ncv::mad<test_scalar_t, test_size_t>, "mad", n_tests, vec1, vec2, wei);
        const test_scalar_t madul4 = test_mad(ncv::mad_unroll4<test_scalar_t, test_size_t>, "madul4", n_tests, vec1, vec2, wei);
        const test_scalar_t madul8 = test_mad(ncv::mad_unroll8<test_scalar_t, test_size_t>, "madul8", n_tests, vec1, vec2, wei);
        const test_scalar_t madeig = test_mad(mad_eig<test_scalar_t, test_size_t>, "madeig", n_tests, vec1, vec2, wei);
        std::cout << std::endl;

        check(mad,      mad, "mad");
        check(madul4,   mad, "madul4");
        check(madul8,   mad, "madul8");
        check(madeig,   mad, "madeig");
}

int main(int argc, char* argv[])
{
        static const size_t min_size = 4;
        static const size_t max_size = 64;
        static const size_t n_tests = 1024 * 1024 * 8;

        for (size_t size = min_size; size <= max_size; size ++)
        {
                test_dot(size, n_tests);
        }
        std::cout << std::endl;

        for (size_t size = min_size; size <= max_size; size ++)
        {
                test_mad(size, n_tests);
        }

	return EXIT_SUCCESS;
}

<commit_msg>style<commit_after>#include "nanocv.h"
#include "common/dot.hpp"
#include "common/mad.hpp"

using namespace ncv;

ncv::thread_pool_t pool;

typedef double test_scalar_t;
typedef ncv::tensor::vector_types_t<test_scalar_t>::tvector     test_vector_t;
typedef ncv::tensor::vector_types_t<test_scalar_t>::tvectors    test_vectors_t;

template
<
        typename tscalar,
        typename tsize
>
tscalar dot_eig(const tscalar* vec1, const tscalar* vec2, tsize size)
{
        return tensor::make_vector(vec1, size).dot(tensor::make_vector(vec2, size));
}

template
<
        typename tscalar,
        typename tsize
>
void mad_eig(const tscalar* idata, tscalar weight, tsize size, tscalar* odata)
{
        tensor::make_vector(odata, size).array() += weight * tensor::make_vector(idata, size).array();
}

template
<
        typename tvector
>
void rand_vector(size_t size, tvector& vector)
{
        vector.resize(size);
        vector.setRandom();
}

template
<
        typename tvector
>
void zero_vector(tvector& vector)
{
        vector.setZero();
}

template
<
        typename top,
        typename tvector,
        typename tscalar = typename tvector::Scalar
>
tscalar test_dot(
        top op, const char* name, size_t n_tests,
        const tvector& vec1, const tvector& vec2)
{
        const ncv::timer_t timer;

        // run multiple tests
        tscalar ret = 0;
        for (size_t t = 0; t < n_tests; t ++)
        {
                ret += op(vec1.data(), vec2.data(), vec1.size());
        }

        const size_t milis = static_cast<size_t>(timer.miliseconds());
        std::cout << name << "= " << text::resize(text::to_string(milis), 4, align::right) << "ms  ";

        return ret;
}

template
<
        typename top,
        typename tvector,
        typename tscalar = typename tvector::Scalar
>
tscalar test_mad(
        top op, const char* name, size_t n_tests,
        const tvector& vec1, const tvector& vec2, tscalar wei)
{
        vector_t cvec1 = vec1;
        vector_t cvec2 = vec2;

        const ncv::timer_t timer;

        // run multiple tests
        for (size_t t = 0; t < n_tests; t ++)
        {
                op(cvec1.data(), wei, cvec1.size(), cvec2.data());
        }

        const size_t milis = static_cast<size_t>(timer.miliseconds());
        std::cout << name << "= " << text::resize(text::to_string(milis), 4, align::right) << "ms  ";

        return cvec2.sum();
}

template
<
        typename tscalar
>
void check(tscalar result, tscalar baseline, const char* name)
{
        const tscalar err = std::fabs(result - baseline);

        if (!math::almost_equal(err, tscalar(0)))
        {
                std::cout << name << " FAILED (diff = " << err << ")!" << std::endl;
        }
}

void test_dot(size_t size, size_t n_tests)
{
        test_vector_t vec1, vec2;

        rand_vector(size, vec1);
        rand_vector(size, vec2);

        const string_t header = (boost::format("%1% x (%2%): ") % n_tests % size).str();
        std::cout << text::resize(header, 16);

        typedef decltype(vec1.size()) test_size_t;

        const test_scalar_t dot    = test_dot(ncv::dot<test_scalar_t, test_size_t>, "dot", n_tests, vec1, vec2);
        const test_scalar_t dotul4 = test_dot(ncv::dot_unroll4<test_scalar_t, test_size_t>, "dotul4", n_tests, vec1, vec2);
        const test_scalar_t dotul8 = test_dot(ncv::dot_unroll8<test_scalar_t, test_size_t>, "dotul8", n_tests, vec1, vec2);
        const test_scalar_t doteig = test_dot(dot_eig<test_scalar_t, test_size_t>, "doteig", n_tests, vec1, vec2);
        std::cout << std::endl;

        check(dot,      dot, "dot");
        check(dotul4,   dot, "dotul4");
        check(dotul8,   dot, "dotul8");
        check(doteig,   dot, "doteig");
}

void test_mad(size_t size, size_t n_tests)
{
        test_vector_t vec1, vec2;

        rand_vector(size, vec1);
        rand_vector(size, vec2);

        test_scalar_t wei;

        wei = vec1(0) + vec2(3);

        const string_t header = (boost::format("%1% x (%2%): ") % n_tests % size).str();
        std::cout << text::resize(header, 16);

        typedef decltype(vec1.size()) test_size_t;

        const test_scalar_t mad    = test_mad(ncv::mad<test_scalar_t, test_size_t>, "mad", n_tests, vec1, vec2, wei);
        const test_scalar_t madul4 = test_mad(ncv::mad_unroll4<test_scalar_t, test_size_t>, "madul4", n_tests, vec1, vec2, wei);
        const test_scalar_t madul8 = test_mad(ncv::mad_unroll8<test_scalar_t, test_size_t>, "madul8", n_tests, vec1, vec2, wei);
        const test_scalar_t madeig = test_mad(mad_eig<test_scalar_t, test_size_t>, "madeig", n_tests, vec1, vec2, wei);
        std::cout << std::endl;

        check(mad,      mad, "mad");
        check(madul4,   mad, "madul4");
        check(madul8,   mad, "madul8");
        check(madeig,   mad, "madeig");
}

int main(int argc, char* argv[])
{
        static const size_t min_size = 4;
        static const size_t max_size = 64;
        static const size_t n_tests = 1024 * 1024 * 8;

        for (size_t size = min_size; size <= max_size; size ++)
        {
                test_dot(size, n_tests);
        }
        std::cout << std::endl;

        for (size_t size = min_size; size <= max_size; size ++)
        {
                test_mad(size, n_tests);
        }

	return EXIT_SUCCESS;
}

<|endoftext|>


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

#include <gtest/gtest.h>
#include <string>

#include "rcutils/filesystem.h"

#include "osrf_testing_tools_cpp/scope_exit.hpp"

static rcutils_allocator_t g_allocator = rcutils_get_default_allocator();

class TestFilesystemFixture : public ::testing::Test
{
public:
  void SetUp()
  {
    EXPECT_TRUE(rcutils_get_cwd(this->cwd, sizeof(this->cwd)));

    test_path = rcutils_join_path(this->cwd, "test", g_allocator);
    ASSERT_FALSE(nullptr == test_path);
  }

  void TearDown()
  {
    g_allocator.deallocate(test_path, g_allocator.state);
  }

  char cwd[1024];
  char * test_path = nullptr;
};

TEST_F(TestFilesystemFixture, get_cwd_nullptr) {
  EXPECT_FALSE(rcutils_get_cwd(NULL, sizeof(this->cwd)));
}

TEST_F(TestFilesystemFixture, join_path) {
  char * path = rcutils_join_path("foo", "bar", g_allocator);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(path, g_allocator.state);
  });
#ifdef _WIN32
  const char * ref_str = "foo\\bar";
#else
  const char * ref_str = "foo/bar";
#endif  // _WIN32
  ASSERT_FALSE(nullptr == path);
  EXPECT_STREQ(ref_str, path);
}

TEST_F(TestFilesystemFixture, to_native_path) {
  {
    char * path = rcutils_to_native_path("/foo/bar/baz", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
#ifdef _WIN32
    const char * ref_str = "\\foo\\bar\\baz";
#else
    const char * ref_str = "/foo/bar/baz";
#endif  // _WIN32
    ASSERT_FALSE(nullptr == path);
    EXPECT_STREQ(ref_str, path);
  }
  {
    char * path = rcutils_to_native_path("/foo//bar/baz", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
#ifdef _WIN32
    const char * ref_str = "\\foo\\\\bar\\baz";
#else
    const char * ref_str = "/foo//bar/baz";
#endif  // _WIN32
    ASSERT_FALSE(nullptr == path);
    EXPECT_STREQ(ref_str, path);
  }
}

TEST_F(TestFilesystemFixture, exists) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_exists(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_exists(path));
  }
}

TEST_F(TestFilesystemFixture, is_directory) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_directory(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_directory(path));
  }
}

TEST_F(TestFilesystemFixture, is_file) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_file(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_file(path));
  }
}

TEST_F(TestFilesystemFixture, is_readable) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable(path));
  }
  {
    char * path =
      rcutils_join_path(this->test_path, "dummy_readable_writable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_nonexisting_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_readable(path));
  }
}

TEST_F(TestFilesystemFixture, is_writable) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_writable(path));
  }
  {
    char * path =
      rcutils_join_path(this->test_path, "dummy_readable_writable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_writable(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_nonexisting_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_writable(path));
  }
}

TEST_F(TestFilesystemFixture, is_readable_and_writable) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable_and_writable(path));
  }
  {
    char * path =
      rcutils_join_path(this->test_path, "dummy_readable_writable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable_and_writable(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_nonexisting_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_readable_and_writable(path));
  }
}

TEST_F(TestFilesystemFixture, mkdir) {
  {
    // Make a new directory
    char * path =
      rcutils_join_path(BUILD_DIR, "mkdir_test_dir", g_allocator);
    ASSERT_FALSE(nullptr == path);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_TRUE(rcutils_mkdir(path));
  }
  {
    // Purposely do it again, to make sure mkdir handles the case where the
    // directory already exists
    char * path =
      rcutils_join_path(BUILD_DIR, "mkdir_test_dir", g_allocator);
    ASSERT_FALSE(nullptr == path);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_TRUE(rcutils_mkdir(path));
  }
  {
    ASSERT_FALSE(rcutils_mkdir(nullptr));
  }
  {
    ASSERT_FALSE(rcutils_mkdir("foo/bar"));
  }
  {
    // Make sure it throws an error when the intermediate path doesn't exist
    char * path =
      rcutils_join_path(BUILD_DIR, "mkdir_test_dir2", g_allocator);
    ASSERT_FALSE(nullptr == path);
    char * path2 =
      rcutils_join_path(path, "mkdir_test_dir3", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path2, g_allocator.state);
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path2);
    ASSERT_FALSE(rcutils_mkdir(path2));
  }
}

TEST_F(TestFilesystemFixture, calculate_directory_size) {
  char * path =
    rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
  size_t size = rcutils_calculate_directory_size(path, g_allocator);
  ASSERT_EQ(5u, size);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(path, g_allocator.state);
  });

  char * non_existing_path = rcutils_join_path(this->test_path, "non_existing_folder", g_allocator);
  size = rcutils_calculate_directory_size(non_existing_path, g_allocator);
  ASSERT_EQ(0u, size);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(non_existing_path, g_allocator.state);
  });
}

TEST_F(TestFilesystemFixture, calculate_file_size) {
  char * path =
    rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
  size_t size = rcutils_get_file_size(path);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(path, g_allocator.state);
  });
  ASSERT_EQ(5u, size);

  char * non_existing_path =
    rcutils_join_path(this->test_path, "non_existing_file.txt", g_allocator);
  size = rcutils_get_file_size(non_existing_path);
  ASSERT_EQ(0u, size);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(non_existing_path, g_allocator.state);
  });
}
<commit_msg>extra byte for windows (#199)<commit_after>// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>
#include <string>

#include "rcutils/filesystem.h"

#include "osrf_testing_tools_cpp/scope_exit.hpp"

static rcutils_allocator_t g_allocator = rcutils_get_default_allocator();

class TestFilesystemFixture : public ::testing::Test
{
public:
  void SetUp()
  {
    EXPECT_TRUE(rcutils_get_cwd(this->cwd, sizeof(this->cwd)));

    test_path = rcutils_join_path(this->cwd, "test", g_allocator);
    ASSERT_FALSE(nullptr == test_path);
  }

  void TearDown()
  {
    g_allocator.deallocate(test_path, g_allocator.state);
  }

  char cwd[1024];
  char * test_path = nullptr;
};

TEST_F(TestFilesystemFixture, get_cwd_nullptr) {
  EXPECT_FALSE(rcutils_get_cwd(NULL, sizeof(this->cwd)));
}

TEST_F(TestFilesystemFixture, join_path) {
  char * path = rcutils_join_path("foo", "bar", g_allocator);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(path, g_allocator.state);
  });
#ifdef _WIN32
  const char * ref_str = "foo\\bar";
#else
  const char * ref_str = "foo/bar";
#endif  // _WIN32
  ASSERT_FALSE(nullptr == path);
  EXPECT_STREQ(ref_str, path);
}

TEST_F(TestFilesystemFixture, to_native_path) {
  {
    char * path = rcutils_to_native_path("/foo/bar/baz", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
#ifdef _WIN32
    const char * ref_str = "\\foo\\bar\\baz";
#else
    const char * ref_str = "/foo/bar/baz";
#endif  // _WIN32
    ASSERT_FALSE(nullptr == path);
    EXPECT_STREQ(ref_str, path);
  }
  {
    char * path = rcutils_to_native_path("/foo//bar/baz", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
#ifdef _WIN32
    const char * ref_str = "\\foo\\\\bar\\baz";
#else
    const char * ref_str = "/foo//bar/baz";
#endif  // _WIN32
    ASSERT_FALSE(nullptr == path);
    EXPECT_STREQ(ref_str, path);
  }
}

TEST_F(TestFilesystemFixture, exists) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_exists(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_exists(path));
  }
}

TEST_F(TestFilesystemFixture, is_directory) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_directory(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_directory(path));
  }
}

TEST_F(TestFilesystemFixture, is_file) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_file(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_file(path));
  }
}

TEST_F(TestFilesystemFixture, is_readable) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable(path));
  }
  {
    char * path =
      rcutils_join_path(this->test_path, "dummy_readable_writable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_nonexisting_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_readable(path));
  }
}

TEST_F(TestFilesystemFixture, is_writable) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_writable(path));
  }
  {
    char * path =
      rcutils_join_path(this->test_path, "dummy_readable_writable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_writable(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_nonexisting_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_writable(path));
  }
}

TEST_F(TestFilesystemFixture, is_readable_and_writable) {
  {
    char * path = rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable_and_writable(path));
  }
  {
    char * path =
      rcutils_join_path(this->test_path, "dummy_readable_writable_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_TRUE(rcutils_is_readable_and_writable(path));
  }
  {
    char * path = rcutils_join_path(this->test_path, "dummy_nonexisting_file.txt", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path);
    EXPECT_FALSE(rcutils_is_readable_and_writable(path));
  }
}

TEST_F(TestFilesystemFixture, mkdir) {
  {
    // Make a new directory
    char * path =
      rcutils_join_path(BUILD_DIR, "mkdir_test_dir", g_allocator);
    ASSERT_FALSE(nullptr == path);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_TRUE(rcutils_mkdir(path));
  }
  {
    // Purposely do it again, to make sure mkdir handles the case where the
    // directory already exists
    char * path =
      rcutils_join_path(BUILD_DIR, "mkdir_test_dir", g_allocator);
    ASSERT_FALSE(nullptr == path);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_TRUE(rcutils_mkdir(path));
  }
  {
    ASSERT_FALSE(rcutils_mkdir(nullptr));
  }
  {
    ASSERT_FALSE(rcutils_mkdir("foo/bar"));
  }
  {
    // Make sure it throws an error when the intermediate path doesn't exist
    char * path =
      rcutils_join_path(BUILD_DIR, "mkdir_test_dir2", g_allocator);
    ASSERT_FALSE(nullptr == path);
    char * path2 =
      rcutils_join_path(path, "mkdir_test_dir3", g_allocator);
    OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
      g_allocator.deallocate(path2, g_allocator.state);
      g_allocator.deallocate(path, g_allocator.state);
    });
    ASSERT_FALSE(nullptr == path2);
    ASSERT_FALSE(rcutils_mkdir(path2));
  }
}

TEST_F(TestFilesystemFixture, calculate_directory_size) {
  char * path =
    rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
  size_t size = rcutils_calculate_directory_size(path, g_allocator);
#ifdef WIN32
  // Due to different line breaks on windows, we have one more byte in the file.
  // See https://github.com/ros2/rcutils/issues/198
  ASSERT_EQ(6u, size);
#else
  ASSERT_EQ(5u, size);
#endif
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(path, g_allocator.state);
  });

  char * non_existing_path = rcutils_join_path(this->test_path, "non_existing_folder", g_allocator);
  size = rcutils_calculate_directory_size(non_existing_path, g_allocator);
  ASSERT_EQ(0u, size);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(non_existing_path, g_allocator.state);
  });
}

TEST_F(TestFilesystemFixture, calculate_file_size) {
  char * path =
    rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
  size_t size = rcutils_get_file_size(path);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(path, g_allocator.state);
  });
#ifdef WIN32
  // Due to different line breaks on windows, we have one more byte in the file.
  // See https://github.com/ros2/rcutils/issues/198
  ASSERT_EQ(6u, size);
#else
  ASSERT_EQ(5u, size);
#endif

  char * non_existing_path =
    rcutils_join_path(this->test_path, "non_existing_file.txt", g_allocator);
  size = rcutils_get_file_size(non_existing_path);
  ASSERT_EQ(0u, size);
  OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
    g_allocator.deallocate(non_existing_path, g_allocator.state);
  });
}
<|endoftext|>