Esempio n. 1
0
llvm::BasicBlock *CleanupScope::runCopying(IRState &irs,
                                           llvm::BasicBlock *sourceBlock,
                                           llvm::BasicBlock *continueWith,
                                           llvm::BasicBlock *unwindTo,
                                           llvm::Value *funclet) {
  if (isCatchSwitchBlock(beginBlock()))
    return continueWith;
  if (exitTargets.empty()) {
    if (!endBlock()->getTerminator())
      // Set up the unconditional branch at the end of the cleanup
      llvm::BranchInst::Create(continueWith, endBlock());
  } else {
    // check whether we have an exit target with the same continuation
    for (CleanupExitTarget &tgt : exitTargets)
      if (tgt.branchTarget == continueWith) {
        tgt.sourceBlocks.push_back(sourceBlock);
        return tgt.cleanupBlocks.front();
      }
  }

  // reuse the original IR if not unwinding and not already used
  bool useOriginal = unwindTo == nullptr && funclet == nullptr;
  for (CleanupExitTarget &tgt : exitTargets) {
    if (tgt.cleanupBlocks.front() == beginBlock()) {
      useOriginal = false;
      break;
    }
  }

  // append new target
  exitTargets.emplace_back(continueWith);
  auto &exitTarget = exitTargets.back();
  exitTarget.sourceBlocks.push_back(sourceBlock);

  if (useOriginal) {
    // change the continuation target if the initial branch was created
    // by another instance with unwinding
    if (continueWith)
      if (auto term = endBlock()->getTerminator())
        if (auto succ = term->getSuccessor(0))
          if (succ != continueWith)
            remapBlocksValue(blocks, succ, continueWith);
    exitTarget.cleanupBlocks = blocks;
  } else {
    // clone the code
    cloneBlocks(blocks, exitTarget.cleanupBlocks, continueWith, unwindTo,
                funclet);
  }
  return exitTarget.cleanupBlocks.front();
}
Esempio n. 2
0
static void parseBlock(
    const Block *block
) {
    startBlock(block);
        auto p = block->chunk->getData();

            auto header = p;
            SKIP(uint32_t, version, p);
            SKIP(uint256_t, prevBlkHash, p);
            SKIP(uint256_t, blkMerkleRoot, p);
            SKIP(uint32_t, blkTime, p);
            SKIP(uint32_t, blkBits, p);
            SKIP(uint32_t, blkNonce, p);

            #if defined PROTOSHARES
                SKIP(uint32_t, nBirthdayA, p);
                SKIP(uint32_t, nBirthdayB, p);
            #endif

            startTXs(p);
                LOAD_VARINT(nbTX, p);
                for(uint64_t txIndex=0; likely(txIndex<nbTX); ++txIndex) {
                    parseTX<false>(block, p);
                }
            endTXs(p);

            #if defined(PEERCOIN) || defined(CLAM) || defined(JUMBUCKS)
                LOAD_VARINT(vchBlockSigSize, p);
                p += vchBlockSigSize;
            #endif

        block->chunk->releaseData();
    endBlock(block);
}
Esempio n. 3
0
static void parseBlock(
    const Block *block
)
{
    startBlock(block);

        const uint8_t *p = block->data;
        const uint8_t *header = p;
        SKIP(uint32_t, version, p);
        SKIP(uint256_t, prevBlkHash, p);
        SKIP(uint256_t, blkMerkleRoot, p);
        SKIP(uint32_t, blkTime, p);
        SKIP(uint32_t, blkBits, p);
        SKIP(uint32_t, blkNonce, p);
        LOAD_VARINT(nbTX, p);
        for(uint64_t txIndex=0; likely(txIndex<nbTX); ++txIndex)
            parseTX<false>(p);

    endBlock(block);
}
Esempio n. 4
0
void Context::endFunction()
{
    endBlock();
    addLine();
}
Esempio n. 5
0
llvm::BasicBlock *CleanupScope::run(IRState &irs, llvm::BasicBlock *sourceBlock,
                                    llvm::BasicBlock *continueWith) {
#if LDC_LLVM_VER >= 308
  if (useMSVCEH())
    return runCopying(irs, sourceBlock, continueWith);
#endif

  if (exitTargets.empty() || (exitTargets.size() == 1 &&
                              exitTargets[0].branchTarget == continueWith)) {
    // We didn't need a branch selector before and still don't need one.
    assert(!branchSelector);

    // Set up the unconditional branch at the end of the cleanup if we have
    // not done so already.
    if (exitTargets.empty()) {
      exitTargets.emplace_back(continueWith);
      llvm::BranchInst::Create(continueWith, endBlock());
    }
    exitTargets.front().sourceBlocks.push_back(sourceBlock);
    return beginBlock();
  }

  // We need a branch selector if we are here...
  if (!branchSelector) {
    // ... and have not created one yet, so do so now.
    branchSelector = new llvm::AllocaInst(llvm::Type::getInt32Ty(irs.context()),
#if LDC_LLVM_VER >= 500
                                          irs.module.getDataLayout().getAllocaAddrSpace(),
#endif
                                          llvm::Twine("branchsel.") +
                                              beginBlock()->getName(),
                                          irs.topallocapoint());

    // Now we also need to store 0 to it to keep the paths that go to the
    // only existing branch target the same.
    for (auto bb : exitTargets.front().sourceBlocks) {
      new llvm::StoreInst(DtoConstUint(0), branchSelector, bb->getTerminator());
    }

    // And convert the BranchInst to the existing branch target to a
    // SelectInst so we can append the other cases to it.
    endBlock()->getTerminator()->eraseFromParent();
    llvm::Value *sel = new llvm::LoadInst(branchSelector, "", endBlock());
    llvm::SwitchInst::Create(
        sel, exitTargets[0].branchTarget,
        1, // Expected number of branches, only for pre-allocating.
        endBlock());
  }

  // If we already know this branch target, figure out the branch selector
  // value and simply insert the store into the source block (prior to the
  // last instruction, which is the branch to the first cleanup).
  for (unsigned i = 0; i < exitTargets.size(); ++i) {
    CleanupExitTarget &t = exitTargets[i];
    if (t.branchTarget == continueWith) {
      new llvm::StoreInst(DtoConstUint(i), branchSelector,
                          sourceBlock->getTerminator());

      // Note: Strictly speaking, keeping this up to date would not be
      // needed right now, because we never to any optimizations that
      // require changes to the source blocks after the initial conversion
      // from one to two branch targets. Keeping this around for now to
      // ease future development, but may be removed to save some work.
      t.sourceBlocks.push_back(sourceBlock);

      return beginBlock();
    }
  }

  // We don't know this branch target yet, so add it to the SwitchInst...
  llvm::ConstantInt *const selectorVal = DtoConstUint(exitTargets.size());
  llvm::cast<llvm::SwitchInst>(endBlock()->getTerminator())
      ->addCase(selectorVal, continueWith);

  // ... insert the store into the source block...
  new llvm::StoreInst(selectorVal, branchSelector,
                      sourceBlock->getTerminator());

  // ... and keep track of it (again, this is unnecessary right now as
  // discussed in the above note).
  exitTargets.emplace_back(continueWith);
  exitTargets.back().sourceBlocks.push_back(sourceBlock);

  return beginBlock();
}
Esempio n. 6
0
static void buildBlockHeaders() {

    info("pass 1 -- walk all blocks and build headers ...");

    size_t nbBlocks = 0;
    size_t baseOffset = 0;
    size_t earlyMissCnt = 0;
    uint8_t buf[8+gHeaderSize];
    const auto sz = sizeof(buf);
    const auto startTime = usecs();
    const auto oneMeg = 1024 * 1024;

    for(const auto &map : mapVec) {

        startMap(0);

        while(1) {

            auto nbRead = read(map.fd, buf, sz);
            if(nbRead<(signed)sz) {
                break;
            }

            startBlock((uint8_t*)0);

            uint8_t *hash = 0;
            Block *prevBlock = 0;
            size_t blockSize = 0;

            getBlockHeader(blockSize, prevBlock, hash, earlyMissCnt, buf);
            if(unlikely(0==hash)) {
                break;
            }

            auto where = lseek(map.fd, (blockSize + 8) - sz, SEEK_CUR);
            auto blockOffset = where - blockSize;
            if(where<0) {
                break;
            }

            auto block = Block::alloc();
            block->init(hash, &map, blockSize, prevBlock, blockOffset);
            gBlockMap[hash] = block;
            endBlock((uint8_t*)0);
            ++nbBlocks;
        }
        baseOffset += map.size;

        auto now = usecs();
        auto elapsed = now - startTime;
        auto bytesPerSec = baseOffset / (elapsed*1e-6);
        auto bytesLeft = gChainSize - baseOffset;
        auto secsLeft = bytesLeft / bytesPerSec;
        fprintf(
            stderr,
            "%.2f%% (%.2f/%.2f Gigs) -- %6d blocks -- %.2f Megs/sec -- ETA %.0f secs -- ELAPSED %.0f secs            \r",
            (100.0*baseOffset)/gChainSize,
            baseOffset/(1000.0*oneMeg),
            gChainSize/(1000.0*oneMeg),
            (int)nbBlocks,
            bytesPerSec*1e-6,
            secsLeft,
            elapsed*1e-6
        );
        fflush(stderr);

        endMap(0);
    }

    if(0==nbBlocks) {
        warning("found no blocks - giving up");
        exit(1);
    }

    char msg[128];
    msg[0] = 0;
    if(0<earlyMissCnt) {
        sprintf(msg, ", %d early link misses", (int)earlyMissCnt);
    }

    auto elapsed = 1e-6*(usecs() - startTime);
    info(
        "pass 1 -- took %.0f secs, %6d blocks, %.2f Gigs, %.2f Megs/secs %s                                            ",
        elapsed,
        (int)nbBlocks,
        (gChainSize * 1e-9),
        (gChainSize * 1e-6) / elapsed,
        msg
    );
}