<commit_before>/* Copyright 2014 <NAME>, all rights reserved. */

#define GRANARY_INTERNAL

#include "arch/driver.h"

#include "granary/cfg/control_flow_graph.h"
#include "granary/cfg/basic_block.h"
#include "granary/cfg/instruction.h"
#include "granary/cfg/lir.h"
#include "granary/cfg/factory.h"

#include "granary/code/register.h"

#include "granary/app.h"
#include "granary/cache.h"
#include "granary/context.h"
#include "granary/index.h"
#include "granary/util.h"

#include "os/annotate.h"
#include "os/module.h"

namespace granary {
extern "C" {

// Address range of Granary/client-specific code that has been explicitly
// exported to instrumented code.
//
// Note: These symbols are defined by `linker.lds`.
extern uint8_t granary_begin_inst_exports;
extern uint8_t granary_end_inst_exports;

// User space-specific functions. If we find that `_fini` is being invoked,
// then we'll redirect execution to `exit_group`, which exit all
// threads in the process.
GRANARY_IF_USER( extern uint8_t _fini; )
GRANARY_IF_USER( extern uint8_t exit_group_ok; )

}  // extern C
enum {
  MAX_NUM_MATERIALIZATION_REQUESTS = 1024
};

// Initialize the factory with an environment and a local control-flow graph.
// The environment is needed for lookups in the code cache index, and the LCFG
// is needed so that blocks can be added.
BlockFactory::BlockFactory(ContextInterface *context_,
                           LocalControlFlowGraph *cfg_)
    : context(context_),
      cfg(cfg_),
      has_pending_request(false),
      generation(0) {}

// Request that a block be materialized. This does nothing if the block is
// not a `DirectBasicBlock`.
void BlockFactory::RequestBlock(BasicBlock *block, BlockRequestKind strategy) {
  if (auto direct_block = DynamicCast<DirectBasicBlock *>(block)) {
    RequestBlock(direct_block, strategy);
  }
}

// Request that a `block` be materialized according to strategy `strategy`.
// If multiple requests are made, then the most fine-grained strategy is
// chosen.
//
// Note: We don't check that `block` is attached to the CFG's block list
//       because in the worst case, it will result in an extra instrumentation
//       loop, and it makes it easier to request blocks ahead of time.
void BlockFactory::RequestBlock(DirectBasicBlock *block,
                                BlockRequestKind strategy) {
  if (REQUEST_LATER != strategy) {
    if (-1 == block->generation) {
      block->generation = generation + 1;
    }
    has_pending_request = true;
    block->materialize_strategy = GRANARY_MAX(block->materialize_strategy,
                                              strategy);
  }
}

namespace {

// Create an intermediate basic block that adapts one version of a block to
// another version.
static CompensationBasicBlock *AdaptToBlock(LocalControlFlowGraph *cfg,
                                            BlockMetaData *meta,
                                            BasicBlock *existing_block) {
  auto adapt_block = new CompensationBasicBlock(cfg, meta);<commit_msg>Minor bug fix in the block factory. The bug can result in an infinite loop.<commit_after>/* Copyright 2014 <NAME>, all rights reserved. */

#define GRANARY_INTERNAL

#include "arch/driver.h"

#include "granary/cfg/control_flow_graph.h"
#include "granary/cfg/basic_block.h"
#include "granary/cfg/instruction.h"
#include "granary/cfg/lir.h"
#include "granary/cfg/factory.h"

#include "granary/code/register.h"

#include "granary/app.h"
#include "granary/cache.h"
#include "granary/context.h"
#include "granary/index.h"
#include "granary/util.h"

#include "os/annotate.h"
#include "os/module.h"

namespace granary {
extern "C" {

// Address range of Granary/client-specific code that has been explicitly
// exported to instrumented code.
//
// Note: These symbols are defined by `linker.lds`.
extern uint8_t granary_begin_inst_exports;
extern uint8_t granary_end_inst_exports;

// User space-specific functions. If we find that `_fini` is being invoked,
// then we'll redirect execution to `exit_group`, which exit all
// threads in the process.
GRANARY_IF_USER( extern uint8_t _fini; )
GRANARY_IF_USER( extern uint8_t exit_group_ok; )

}  // extern C
enum {
  MAX_NUM_MATERIALIZATION_REQUESTS = 1024
};

// Initialize the factory with an environment and a local control-flow graph.
// The environment is needed for lookups in the code cache index, and the LCFG
// is needed so that blocks can be added.
BlockFactory::BlockFactory(ContextInterface *context_,
                           LocalControlFlowGraph *cfg_)
    : context(context_),
      cfg(cfg_),
      has_pending_request(false),
      generation(0) {}

// Request that a block be materialized. This does nothing if the block is
// not a `DirectBasicBlock`.
void BlockFactory::RequestBlock(BasicBlock *block, BlockRequestKind strategy) {
  if (auto direct_block = DynamicCast<DirectBasicBlock *>(block)) {
    RequestBlock(direct_block, strategy);
  }
}

// Request that a `block` be materialized according to strategy `strategy`.
// If multiple requests are made, then the most fine-grained strategy is
// chosen.
//
// Note: We don't check that `block` is attached to the CFG's block list
//       because in the worst case, it will result in an extra instrumentation
//       loop, and it makes it easier to request blocks ahead of time.
void BlockFactory::RequestBlock(DirectBasicBlock *block,
                                BlockRequestKind strategy) {
  if (REQUEST_LATER != strategy) {
    if (-1 == block->generation) {
      block->generation = generation + 1;
    }
    auto old_strategy = block->materialize_strategy;
    block->materialize_strategy = GRANARY_MAX(block->materialize_strategy,
                                              strategy);
    if (old_strategy != block->materialize_strategy) {
      has_pending_request = true;
    }
  }
}

namespace {

// Create an intermediate basic block that adapts one version of a block to
// another version.
static CompensationBasicBlock *AdaptToBlock(LocalControlFlowGraph *cfg,
                                            BlockMetaData *meta,
                                            BasicBlock *existing_block) {
  auto adapt_block = new CompensationBasicBlock(cfg, meta);
{'fraction_non_alphanumeric': 0.09511568123393316, 'fraction_numerical': 0.004820051413881748, 'mean_word_length': 3.214624238320921, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2321339', 'n_tokens_mistral': 1848, 'n_tokens_neox': 1769, 'n_words': 579}