reorganize live variable analysis to use it's functions further
This commit is contained in:
@@ -17,6 +17,8 @@ using std::set;
|
||||
using std::unordered_map;
|
||||
using std::list;
|
||||
|
||||
using LIVE_VARIABLES::fcall;
|
||||
|
||||
namespace SAPFOR
|
||||
{
|
||||
bool BasicBlock::addLive(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& to_add, bool in) {
|
||||
@@ -114,89 +116,77 @@ namespace SAPFOR
|
||||
}
|
||||
}
|
||||
|
||||
struct fcall
|
||||
bool fcall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
|
||||
{
|
||||
private:
|
||||
bool tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
|
||||
if (b == block || dest.find(block) == dest.end())
|
||||
{
|
||||
if (b == block || dest.find(block) == dest.end())
|
||||
{
|
||||
dest.insert(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
dest.insert(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
FuncInfo* func;
|
||||
return false;
|
||||
}
|
||||
|
||||
map<int, set<SAPFOR::BasicBlock*>> live_after;
|
||||
set<int> dead_after;
|
||||
fcall::fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
|
||||
{
|
||||
block = b;
|
||||
func = f;
|
||||
|
||||
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> commons_live_after;
|
||||
set<SAPFOR::Argument*> commons_dead_after;
|
||||
int param_size = p.size();
|
||||
params = vector<SAPFOR::Argument*>(param_size, NULL);
|
||||
|
||||
vector<SAPFOR::Argument*> params;
|
||||
SAPFOR::BasicBlock* block;
|
||||
for (int i = 0; i < param_size; i++)
|
||||
if (f->funcParams.isArgOut(i))
|
||||
params[i] = p[i];
|
||||
}
|
||||
|
||||
fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
|
||||
void fcall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b)
|
||||
{
|
||||
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
||||
{
|
||||
block = b;
|
||||
func = f;
|
||||
|
||||
int param_size = p.size();
|
||||
params = vector<SAPFOR::Argument*>(param_size, NULL);
|
||||
|
||||
for (int i = 0; i < param_size; i++)
|
||||
if (f->funcParams.isArgOut(i))
|
||||
params[i] = p[i];
|
||||
if (commons_dead_after.find(arg) == commons_dead_after.end())
|
||||
tryInsert(commons_live_after[arg], b);
|
||||
}
|
||||
|
||||
void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b)
|
||||
auto it = find(params.begin(), params.end(), arg);
|
||||
if (it != params.end())
|
||||
{
|
||||
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
||||
{
|
||||
if (commons_dead_after.find(arg) == commons_dead_after.end())
|
||||
tryInsert(commons_live_after[arg], b);
|
||||
}
|
||||
|
||||
auto it = find(params.begin(), params.end(), arg);
|
||||
if (it != params.end())
|
||||
{
|
||||
int idx = it - params.begin();
|
||||
if (dead_after.find(idx) == dead_after.end())
|
||||
tryInsert(live_after[idx], b);
|
||||
}
|
||||
int idx = it - params.begin();
|
||||
if (dead_after.find(idx) == dead_after.end())
|
||||
tryInsert(live_after[idx], b);
|
||||
}
|
||||
}
|
||||
|
||||
void make_dead(SAPFOR::Argument* arg)
|
||||
void fcall::make_dead(SAPFOR::Argument* arg)
|
||||
{
|
||||
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
||||
{
|
||||
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
||||
if (commons_live_after.find(arg) == commons_live_after.end())
|
||||
commons_dead_after.insert(arg);
|
||||
|
||||
auto it = find(params.begin(), params.end(), arg);
|
||||
if (it != params.end())
|
||||
{
|
||||
int idx = it - params.begin();
|
||||
dead_after.insert(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void updateFromOut()
|
||||
auto it = find(params.begin(), params.end(), arg);
|
||||
if (it != params.end())
|
||||
{
|
||||
for (const auto& p : block->getLiveOut())
|
||||
for (auto b : p.second)
|
||||
make_live(p.first, b);
|
||||
int idx = it - params.begin();
|
||||
if (live_after.find(idx) == live_after.end())
|
||||
dead_after.insert(idx);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void fcall::updateFromOut()
|
||||
{
|
||||
for (const auto& p : block->getLiveOut())
|
||||
for (auto b : p.second)
|
||||
make_live(p.first, b);
|
||||
}
|
||||
|
||||
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
|
||||
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead);
|
||||
|
||||
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName);
|
||||
const map<string, FuncInfo*>& funcByName, bool interprocedural);
|
||||
|
||||
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>> {
|
||||
private:
|
||||
@@ -234,11 +224,11 @@ public:
|
||||
};
|
||||
|
||||
LiveVarAnalysisNode(SAPFOR::BasicBlock* block, vector<SAPFOR::Argument*>& formal_parameters,
|
||||
vector<fcall>& fcalls, const map<string, FuncInfo*>& funcByName)
|
||||
vector<fcall>& fcalls, const map<string, FuncInfo*>& funcByName)
|
||||
{
|
||||
setBlock(block);
|
||||
|
||||
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName);
|
||||
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
|
||||
|
||||
for (SAPFOR::Argument* arg : live)
|
||||
getBlock()->addLiveIn({ { arg, { getBlock() } } });
|
||||
@@ -251,8 +241,7 @@ protected:
|
||||
vector<fcall>& fcalls;
|
||||
const map<string, FuncInfo*>& funcByName;
|
||||
|
||||
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override
|
||||
{
|
||||
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
|
||||
return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName);
|
||||
};
|
||||
public:
|
||||
@@ -261,107 +250,151 @@ public:
|
||||
{ };
|
||||
};
|
||||
|
||||
//Build use and def sets of block. Result are stored in use and def
|
||||
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName)
|
||||
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
|
||||
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
||||
{
|
||||
set<SAPFOR::Argument*> tmp_use, tmp_def;
|
||||
for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() })
|
||||
if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_)
|
||||
formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg;
|
||||
|
||||
vector<SAPFOR::Argument*> lastParamRef;
|
||||
bool fcall_added;
|
||||
SAPFOR::Argument* res_arg = NULL;
|
||||
|
||||
for (auto ir_block : block->getInstructions())
|
||||
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
|
||||
SAPFOR::CFG_OP instr_operation = instr->getOperation();
|
||||
if (hasStoreStructure(instr_operation))
|
||||
{
|
||||
fcall_added = false;
|
||||
SAPFOR::Instruction* instr = ir_block->getInstruction();
|
||||
for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() })
|
||||
if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_)
|
||||
formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg;
|
||||
res_arg = instr->getArg1();
|
||||
set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2() };
|
||||
use.insert(instr_args.begin(), instr_args.end());
|
||||
}
|
||||
else if (instr_operation == SAPFOR::CFG_OP::PARAM)
|
||||
{
|
||||
lastParamRef[last_param_ref_index--] = instr->getArg1();
|
||||
}
|
||||
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
|
||||
{
|
||||
res_arg = instr->getResult();
|
||||
|
||||
set<SAPFOR::Argument*> res = {}, args = {};
|
||||
SAPFOR::Argument* res_arg = NULL;
|
||||
last_param_ref_size = stoi(instr->getArg2()->getValue());
|
||||
|
||||
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
|
||||
SAPFOR::CFG_OP instr_operation = instr->getOperation();
|
||||
if (hasStoreStructure(instr_operation)) {
|
||||
res_arg = instr->getArg1();
|
||||
std::set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2()};
|
||||
insertIfVar(instr_args.begin(), instr_args.end(), args);
|
||||
}
|
||||
else if (instr_operation == SAPFOR::CFG_OP::PARAM)
|
||||
lastParamRef.push_back(instr->getArg1());
|
||||
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
|
||||
lastParamRef.clear();
|
||||
lastParamRef.resize(last_param_ref_size);
|
||||
|
||||
last_param_ref_index = last_param_ref_size - 1;
|
||||
|
||||
fName = instr->getArg1()->getValue();
|
||||
}
|
||||
else if (skip.find(instr_operation) == skip.end())
|
||||
{
|
||||
//default
|
||||
res_arg = instr->getResult();
|
||||
std::set<SAPFOR::Argument*> intr_args = { instr->getArg1(), instr->getArg2() };
|
||||
use.insert(intr_args.begin(), intr_args.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
//skip
|
||||
return;
|
||||
}
|
||||
|
||||
if ((instr_operation == SAPFOR::CFG_OP::F_CALL || instr_operation == SAPFOR::CFG_OP::PARAM) && last_param_ref_index < 0) {
|
||||
auto func_it = funcByName.find(fName);
|
||||
if (func_it != funcByName.end())
|
||||
{
|
||||
res_arg = instr->getResult();
|
||||
fcalls.push_back(fcall(func_it->second, block, lastParamRef));
|
||||
|
||||
int count = stoi(instr->getArg2()->getValue());
|
||||
if (lastParamRef.size() != count)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
auto r_it = fcalls.rbegin();
|
||||
auto r_end = fcalls.rend();
|
||||
|
||||
const string& fName = instr->getArg1()->getValue();
|
||||
auto func_it = funcByName.find(fName);
|
||||
if (func_it != funcByName.end())
|
||||
{
|
||||
fcalls.push_back(fcall(func_it->second, block, lastParamRef));
|
||||
fcall_added = true;
|
||||
}
|
||||
|
||||
set<SAPFOR::Argument*> make_live, make_dead;
|
||||
if (fName == "_READ")
|
||||
res.insert(lastParamRef.begin(), lastParamRef.end());
|
||||
else if (getLiveDead(lastParamRef, fName, make_live, make_dead))
|
||||
{
|
||||
insertIfVar(make_live.begin(), make_live.end(), args);
|
||||
insertIfVar(make_dead.begin(), make_dead.end(), res);
|
||||
}
|
||||
else
|
||||
insertIfVar(lastParamRef.begin(), lastParamRef.end(), args);
|
||||
|
||||
lastParamRef.clear();
|
||||
}
|
||||
else if(skip.find(instr_operation) == skip.end())
|
||||
{
|
||||
//default
|
||||
res_arg = instr->getResult();
|
||||
std::set<SAPFOR::Argument*> intr_args = { instr->getArg1(), instr->getArg2() };
|
||||
insertIfVar(intr_args.begin(), intr_args.end(), args);
|
||||
}
|
||||
else {
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
if (res_arg && res_arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
res.insert(res_arg);
|
||||
|
||||
for (auto e : args)
|
||||
if (!tmp_def.count(e))
|
||||
tmp_use.insert(e);
|
||||
|
||||
for(auto e : res)
|
||||
if (!tmp_use.count(e))
|
||||
tmp_def.insert(e);
|
||||
|
||||
auto r_it = fcalls.rbegin();
|
||||
auto r_end = fcalls.rend();
|
||||
if (fcall_added && r_it != r_end)
|
||||
r_it++;
|
||||
|
||||
while (r_it != r_end && r_it->block == block)
|
||||
{
|
||||
for (auto e : args)
|
||||
r_it->make_live(e, block);
|
||||
|
||||
for (auto e : res)
|
||||
for (auto e : def)
|
||||
r_it->make_dead(e);
|
||||
|
||||
r_it++;
|
||||
for (auto e : use)
|
||||
r_it->make_live(e, block);
|
||||
}
|
||||
|
||||
set<SAPFOR::Argument*> make_live, make_dead;
|
||||
if (fName == "_READ")
|
||||
def.insert(lastParamRef.begin(), lastParamRef.end());
|
||||
else if (interprocedural && getLiveDead(lastParamRef, fName, make_live, make_dead))
|
||||
{
|
||||
use.insert(make_live.begin(), make_live.end());
|
||||
def.insert(make_dead.begin(), make_dead.end());
|
||||
}
|
||||
else
|
||||
use.insert(lastParamRef.begin(), lastParamRef.end());
|
||||
|
||||
last_param_ref_index = 0;
|
||||
last_param_ref_size = 0;
|
||||
|
||||
lastParamRef.clear();
|
||||
fName = "";
|
||||
}
|
||||
|
||||
if (res_arg)
|
||||
def.insert(res_arg);
|
||||
}
|
||||
|
||||
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
|
||||
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
||||
{
|
||||
set<SAPFOR::Argument*> res, args;
|
||||
|
||||
getUseDefForInstruction(block, instr,
|
||||
args, res,
|
||||
formal_parameters, fcalls,
|
||||
lastParamRef, last_param_ref_index, last_param_ref_size,
|
||||
fName, funcByName,
|
||||
interprocedural
|
||||
);
|
||||
|
||||
for (auto e : res)
|
||||
{
|
||||
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
{
|
||||
def.insert(e);
|
||||
use.erase(e);
|
||||
}
|
||||
}
|
||||
|
||||
use = tmp_use;
|
||||
def = tmp_def;
|
||||
for (auto e : args)
|
||||
{
|
||||
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
{
|
||||
use.insert(e);
|
||||
def.erase(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Build use and def sets of block. Result are stored in use and def
|
||||
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
||||
{
|
||||
vector<SAPFOR::Argument*> lastParamRef;
|
||||
int last_param_ref_index = 0, last_param_ref_size = 0;
|
||||
string fName;
|
||||
|
||||
const auto& instructions = block->getInstructions();
|
||||
auto ir_block_it = instructions.rbegin(), ir_block_end = instructions.rend();
|
||||
|
||||
for (; ir_block_it != ir_block_end; ir_block_it++)
|
||||
{
|
||||
updateUseDefForInstruction(block, (*ir_block_it)->getInstruction(),
|
||||
use, def,
|
||||
formal_parameters, fcalls,
|
||||
lastParamRef, last_param_ref_index, last_param_ref_size,
|
||||
fName, funcByName,
|
||||
interprocedural
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// prints info about live variables
|
||||
@@ -379,7 +412,7 @@ void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_p
|
||||
for (const auto& live : byBB->getLiveIn())
|
||||
{
|
||||
__spf_print(1, " %s:", live.first->getValue().c_str());
|
||||
for(auto use : live.second)
|
||||
for (auto use : live.second)
|
||||
__spf_print(1, " %d", use->getNumber());
|
||||
__spf_print(1, "\n");
|
||||
}
|
||||
@@ -482,8 +515,8 @@ static void fillLiveDeadArgs(const FuncInfo* func, const vector<SAPFOR::BasicBlo
|
||||
// unite global arguments and actual parameters with given indexes for function
|
||||
// stores the result in the last argument
|
||||
bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
|
||||
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
|
||||
const string& func_name, set<SAPFOR::Argument*>& result)
|
||||
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
|
||||
const string& func_name, set<SAPFOR::Argument*>& result)
|
||||
{
|
||||
auto globals_it = params_and_globals.find(func_name);
|
||||
|
||||
@@ -498,7 +531,7 @@ bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
|
||||
for (int idx : param_indexes)
|
||||
{
|
||||
if (idx < params_size) {
|
||||
if(params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
if (params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
result.insert(params[idx]);
|
||||
}
|
||||
else
|
||||
@@ -511,10 +544,10 @@ bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
|
||||
|
||||
// fill sets of arguments wich becomes live or dead after call with parameters params
|
||||
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
|
||||
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead)
|
||||
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead)
|
||||
{
|
||||
return joinGlobalsWithParameters(params, live_by_func, func_name, live) &&
|
||||
joinGlobalsWithParameters(params, dead_by_func, func_name, dead);
|
||||
joinGlobalsWithParameters(params, dead_by_func, func_name, dead);
|
||||
}
|
||||
|
||||
// entrypoint for live variable analysis pass
|
||||
|
||||
@@ -1,6 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "CFGraph.h"
|
||||
|
||||
namespace LIVE_VARIABLES
|
||||
{
|
||||
struct fcall
|
||||
{
|
||||
private:
|
||||
bool tryInsert(std::set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b);
|
||||
public:
|
||||
FuncInfo* func;
|
||||
|
||||
std::map<int, std::set<SAPFOR::BasicBlock*>> live_after;
|
||||
std::set<int> dead_after;
|
||||
|
||||
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> commons_live_after;
|
||||
std::set<SAPFOR::Argument*> commons_dead_after;
|
||||
|
||||
std::vector<SAPFOR::Argument*> params;
|
||||
SAPFOR::BasicBlock* block;
|
||||
|
||||
fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const std::vector<SAPFOR::Argument*>& p);
|
||||
|
||||
void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b);
|
||||
void make_dead(SAPFOR::Argument* arg);
|
||||
|
||||
void updateFromOut();
|
||||
};
|
||||
}
|
||||
|
||||
template <class IT, class DEST>
|
||||
void insertIfVar(IT begin, IT end, DEST& to) {
|
||||
for (auto it = begin; it != end; it++)
|
||||
@@ -8,6 +37,12 @@ void insertIfVar(IT begin, IT end, DEST& to) {
|
||||
to.insert(*it);
|
||||
};
|
||||
|
||||
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
std::set<SAPFOR::Argument*>& use, std::set<SAPFOR::Argument*>& def,
|
||||
std::vector<SAPFOR::Argument*>& formal_parameters, std::vector<LIVE_VARIABLES::fcall>& fcalls,
|
||||
std::vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
|
||||
std::string& fName, const std::map<std::string, FuncInfo*>& funcByName, bool interprocedural);
|
||||
|
||||
void runLiveVariableAnalysis(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);
|
||||
|
||||
void doDumpLive(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);
|
||||
|
||||
Reference in New Issue
Block a user