本文整理汇总了C++中FunctionState类的典型用法代码示例。如果您正苦于以下问题:C++ FunctionState类的具体用法?C++ FunctionState怎么用?C++ FunctionState使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了FunctionState类的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: runAnalysis
void IntraAnalysisResultsToDotFiles::runAnalysis()
{
set<FunctionState*> allFuncs = FunctionState::getAllDefinedFuncs();
// Go through functions one by one, call an intra-procedural analysis on each of them
// iterate over all functions with bodies
for(set<FunctionState*>::iterator it=allFuncs.begin(); it!=allFuncs.end(); it++)
{
FunctionState* fState = *it;
// compose the output file name as filename_mangled_function_name.dot
Function *func = & (fState->getFunc());
assert (func != NULL);
SgFunctionDefinition* proc = func->get_definition();
string file_name = StringUtility::stripPathFromFileName(proc->get_file_info()->get_filename());
string file_func_name= file_name+ "_"+proc->get_mangled_name().getString();
string full_output = file_func_name +"_cfg.dot";
std::ofstream ostr(full_output.c_str());
ostr << "digraph " << "mygraph" << " {\n";
analysisStatesToDOT* dot_analysis = dynamic_cast <analysisStatesToDOT*> ( intraAnalysis);
assert (dot_analysis != NULL);
dot_analysis->ostr = &ostr;
dot_analysis->runAnalysis(fState->func, &(fState->state));
ostr << "}\n";
}
}
示例2:
gmCodeGenPrivate::FunctionState * gmCodeGenPrivate::PopFunction()
{
if(m_currentFunction)
{
m_currentFunction->Reset();
m_currentFunction = m_functionStack.GetPrev(m_currentFunction);
if(!m_functionStack.IsValid(m_currentFunction))
{
m_currentFunction = NULL;
}
}
return m_currentFunction;
}
示例3: setState
void InterpreterThread::setState(ByteInputStream& stream) {
functionStackLimit = stream.getUInt32();
uint64_t stackSize = stream.getUInt64();
for (std::uint64_t i = 0; i < stackSize; i++) {
FunctionState functionState;
functionState.setState(stream);
}
uint64_t instructionStackSize = stream.getUInt64();
instructionStack_.resize(instructionStackSize);
for (uint64_t i = 0; i < instructionStackSize; i++) {
instructionStack_.at(i).setThread(*this);
instructionStack_.at(i).setState(stream, env_);
}
uint64_t numberOfHeaps = stream.getUInt64();
for (uint64_t i = 0; i < numberOfHeaps; i++) {
std::string moduleName = stream.getString();
Heap& heap = heapsByModuleName_[moduleName] = Heap();
heap.setState(stream);
}
}
示例4: GM_NEW
gmCodeGenPrivate::FunctionState * gmCodeGenPrivate::PushFunction()
{
if(m_currentFunction)
{
if(m_currentFunction != m_functionStack.GetLast())
{
m_currentFunction = m_functionStack.GetNext(m_currentFunction);
}
else
{
m_currentFunction = GM_NEW( FunctionState() );
m_functionStack.InsertLast(m_currentFunction);
}
}
else
{
if(m_functionStack.IsEmpty())
{
m_currentFunction = GM_NEW( FunctionState() );
m_functionStack.InsertLast(m_currentFunction);
}
else
{
m_currentFunction = m_functionStack.GetFirst();
}
}
m_currentFunction->Reset();
m_currentFunction->m_byteCode.SetSwapEndianOnWrite(m_hooks->SwapEndian());
// if we are debugging, set up some line number debugging.
if(m_debug)
{
m_currentFunction->m_byteCode.m_emitCallback = gmLineNumberCallback;
}
return m_currentFunction;
}
示例5: printComparable
void printComparable(llvm::raw_ostream &Out, FunctionState const &State)
{
Out << " Function [Index=" << State.getIndex() << "]\n";
Out << " Allocas:\n";
for (auto const &Alloca : State.getAllocas()) {
Out << " " << Alloca.getInstructionIndex()
<< " =[" << Alloca.getElementCount()
<< "x" << Alloca.getElementSize()
<< "]\n";
}
Out << " Instruction values [Active=";
if (State.getActiveInstructionIndex().assigned(0))
Out << State.getActiveInstructionIndex().get<0>();
else
Out << "unassigned";
Out << "]:\n";
auto const InstructionCount = State.getInstructionCount();
for (std::size_t i = 0; i < InstructionCount; ++i) {
auto const Instruction = State.getInstruction(i);
auto const Type = Instruction->getType();
if (llvm::isa<llvm::IntegerType>(Type)) {
auto const UValue = State.getValueUInt64(Instruction);
if (UValue.assigned<uint64_t>()) {
auto const SValue = State.getValueInt64(Instruction);
assert(SValue.assigned<int64_t>());
Out << " " << i << " = (int64_t)" << SValue.get< int64_t>()
<< ", (uint64_t)" << UValue.get<uint64_t>() << "\n";
}
}
else if (Type->isPointerTy()) {
auto const Value = State.getValuePtr(Instruction);
if (Value.assigned<stateptr_ty>()) {
Out << " " << i << " = \n";
// TODO: a comparable pointer representation (this requires us to
// determine the allocation that a pointer references, and then
// display the pointer value relative to that allocation).
}
}
else if (Type->isFloatTy()) {
auto const Value = State.getValueFloat(Instruction);
if (Value.assigned<float>()) {
Out << " " << i << " = (float)" << Value.get<float>() << "\n";
}
}
else if (Type->isDoubleTy()) {
auto const Value = State.getValueDouble(Instruction);
if (Value.assigned<double>()) {
Out << " " << i << " = (double)" << Value.get<double>() << "\n";
}
}
else if (Type->isX86_FP80Ty() || Type->isFP128Ty() || Type->isPPC_FP128Ty())
{
auto const Value = State.getValueAPFloat(Instruction);
if (Value.assigned<llvm::APFloat>()) {
llvm::SmallString<32> Buffer;
Value.get<llvm::APFloat>().toString(Buffer);
Out << " " << i << " = (long double)" << Buffer << "\n";
}
}
}
}
示例6: GenStmtForEach
bool gmCodeGenPrivate::GenStmtForEach(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
unsigned int breakAddress, continueAddress, loc1, loc2;
// Generate table
if(!Generate(a_node->m_children[0], a_byteCode))
{
return false;
}
PushLoop();
// Push the first iterator
a_byteCode->Emit(BC_PUSHINT, (gmuint32) -2); // first iterator value.
continueAddress = a_byteCode->Tell();
// Generate call
const char * keyVar = s_tempVarName1;
if(a_node->m_children[2]) keyVar = a_node->m_children[2]->m_data.m_string;
const char * valueVar = a_node->m_children[1]->m_data.m_string;
gmuint16 keyOffset = (gmuint16) m_currentFunction->SetVariableType(keyVar, CTVT_LOCAL);
gmuint16 valueOffset = (gmuint16) m_currentFunction->SetVariableType(valueVar, CTVT_LOCAL);
gmuint32 opcode = (keyOffset << 16) | (valueOffset & 0xffff);
loc1 = a_byteCode->Tell();
a_byteCode->Emit(BC_FOREACH, opcode);
// Skip space for jump
loc2 = a_byteCode->Skip(SIZEOF_BC_BRA);
// Generate body
if(!Generate(a_node->m_children[3], a_byteCode))
{
PopLoop();
return false;
}
a_byteCode->EmitPtr(BC_BRA, (gmuint32) loc1);
breakAddress = a_byteCode->Seek(loc2);
a_byteCode->EmitPtr(BC_BRZ, breakAddress);
a_byteCode->Seek(breakAddress);
// pop table and iterator
a_byteCode->Emit(BC_POP2);
ApplyPatches(m_loopStack[m_currentLoop].m_breaks, a_byteCode, breakAddress);
ApplyPatches(m_loopStack[m_currentLoop].m_continues, a_byteCode, continueAddress);
PopLoop();
return true;
}
示例7: GenStmtFork
bool gmCodeGenPrivate::GenStmtFork(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
GM_ASSERT(a_node->m_type == CTNT_STATEMENT && a_node->m_subType == CTNST_FORK );
gmuint32 loc1,loc2;
// create the var for the thread id
const char * valname = 0;
gmuint32 valref = 0;
if ( a_node->m_children[1])
{
valname = a_node->m_children[1]->m_data.m_string;
valref = m_currentFunction->SetVariableType( valname, CTVT_LOCAL );
}
loc1 = a_byteCode->Skip( SIZEOF_BC_BRA );
if (!valname) a_byteCode->Emit( BC_POP ); // if not specified then just pop
else a_byteCode->Emit( BC_SETLOCAL, valref ); // store the thread id
if (!Generate(a_node->m_children[0], a_byteCode )) return false;
a_byteCode->Emit( BC_RET );
loc2 = a_byteCode->Seek( loc1 );
a_byteCode->Emit( BC_FORK, loc2 );
a_byteCode->Seek( loc2 );
if (!valname) a_byteCode->Emit( BC_POP ); // if not specified then just pop
else a_byteCode->Emit( BC_SETLOCAL, valref ); // store the thread id
return true;
}
示例8: GenDeclVariable
bool gmCodeGenPrivate::GenDeclVariable(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
GM_ASSERT(a_node->m_type == CTNT_DECLARATION && a_node->m_subType == CTNDT_VARIABLE);
GM_ASSERT(m_currentFunction);
m_currentFunction->SetVariableType(a_node->m_children[0]->m_data.m_string, (gmCodeTreeVariableType) a_node->m_subTypeType);
return true;
}
示例9: GenExprIdentifier
bool gmCodeGenPrivate::GenExprIdentifier(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_IDENTIFIER);
// if local, get local regardless
// if member, get this
// if global, get global
// get global
if((a_node->m_flags & gmCodeTreeNode::CTN_MEMBER) > 0)
{
return a_byteCode->EmitPtr(BC_GETTHIS, m_hooks->GetSymbolId(a_node->m_data.m_string));
}
gmCodeTreeVariableType type;
int offset = m_currentFunction->GetVariableOffset(a_node->m_data.m_string, type);
if(offset >= 0 && type == CTVT_LOCAL)
{
return a_byteCode->Emit(BC_GETLOCAL, (gmuint32) offset);
}
else if(offset != -2)
{
if(type == CTVT_MEMBER)
{
return a_byteCode->EmitPtr(BC_GETTHIS, m_hooks->GetSymbolId(a_node->m_data.m_string));
}
else if(type == CTVT_GLOBAL)
{
return a_byteCode->EmitPtr(BC_GETGLOBAL, m_hooks->GetSymbolId(a_node->m_data.m_string));
}
if(m_log) m_log->LogEntry("internal error");
return false;
}
return a_byteCode->EmitPtr(BC_GETGLOBAL, m_hooks->GetSymbolId(a_node->m_data.m_string));
}
示例10: GenExprFunction
bool gmCodeGenPrivate::GenExprFunction(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_FUNCTION);
gmptr id = m_hooks->GetFunctionId();
a_byteCode->EmitPtr(BC_PUSHFN, id);
// Create the function
PushFunction();
// Get a debug function name as the name of the variable the function is assigned to
if(m_debug && a_node->m_parent && a_node->m_parent->m_type == CTNT_EXPRESSION && a_node->m_parent->m_subType == CTNET_OPERATION &&
(a_node->m_parent->m_subTypeType == CTNOT_ASSIGN || a_node->m_parent->m_subTypeType == CTNOT_ASSIGN_FIELD) && a_node->m_parent->m_children[1] == a_node)
{
const gmCodeTreeNode * debugName = a_node->m_parent->m_children[0];
if(debugName && debugName->m_type == CTNT_EXPRESSION && debugName->m_subType == CTNET_IDENTIFIER)
{
}
else if(debugName->m_type == CTNT_EXPRESSION && debugName->m_subType == CTNET_OPERATION &&
debugName->m_subTypeType == CTNOT_DOT)
{
debugName = debugName->m_children[1];
}
else
{
debugName = NULL;
}
if(debugName)
{
GM_ASSERT(debugName->m_type == CTNT_EXPRESSION && debugName->m_subType == CTNET_IDENTIFIER);
m_currentFunction->m_debugName = debugName->m_data.m_string;
}
}
// Parameters
const gmCodeTreeNode * params = a_node->m_children[0];
int numParams = 0;
while(params)
{
const gmCodeTreeNode * param = params->m_children[0];
GM_ASSERT(param->m_type == CTNT_EXPRESSION && param->m_subType == CTNET_IDENTIFIER);
if(m_currentFunction->SetVariableType(param->m_data.m_string, CTVT_LOCAL) != numParams)
{
if(m_log) m_log->LogEntry("error (%d) parameter %s already declared", param->m_lineNumber, param->m_data.m_string);
PopFunction();
return false;
}
++numParams;
params = params->m_sibling;
}
// Generate the code
bool res = Generate(a_node->m_children[1], &m_currentFunction->m_byteCode);
// Generate a return incase the function didnt have one.
m_currentFunction->m_byteCode.Emit(BC_RET);
if(res)
{
// Create a locals table
const char ** locals = NULL;
if(m_debug)
{
locals = (const char **) alloca(sizeof(const char *) * m_currentFunction->m_numLocals);
memset(locals, 0, sizeof(const char *) * m_currentFunction->m_numLocals);
for(gmuint v = 0; v < m_currentFunction->m_variables.Count(); ++v)
{
Variable &variable = m_currentFunction->m_variables[v];
if(variable.m_offset != -1)
{
locals[variable.m_offset] = variable.m_symbol;
}
}
}
// Add the function to the hooks.
gmSortDebugLines(m_currentFunction->m_lineInfo);
gmFunctionInfo info;
info.m_id = id;
info.m_root = false;
info.m_byteCode = m_currentFunction->m_byteCode.GetData();
info.m_byteCodeLength = m_currentFunction->m_byteCode.Tell();
info.m_numParams = numParams;
info.m_numLocals = m_currentFunction->m_numLocals - numParams;
info.m_symbols = locals;
info.m_maxStackSize = m_currentFunction->m_byteCode.GetMaxTos();
info.m_lineInfoCount = m_currentFunction->m_lineInfo.Count();
info.m_lineInfo = m_currentFunction->m_lineInfo.GetData();
info.m_debugName = m_currentFunction->m_debugName;
m_hooks->AddFunction(info);
//gmByteCodePrint(stdout, info.m_byteCode, info.m_byteCodeLength);
}
PopFunction();
//.........这里部分代码省略.........
示例11: GenExprCall
bool gmCodeGenPrivate::GenExprCall(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_CALL);
// mark the stack.
int stackLevel = a_byteCode->GetTos();
// if callee is a dot function, push left side of dot as 'this'
const gmCodeTreeNode * callee = a_node->m_children[0];
if(callee->m_type == CTNT_EXPRESSION && callee->m_subType == CTNET_OPERATION && callee->m_subTypeType == CTNOT_DOT)
{
if(!Generate(callee->m_children[0], a_byteCode)) return false;
a_byteCode->Emit(BC_DUP);
a_byteCode->EmitPtr(BC_GETDOT, m_hooks->GetSymbolId(callee->m_children[1]->m_data.m_string));
}
else
{
if(a_node->m_children[2])
{
if(!Generate(a_node->m_children[2], a_byteCode)) return false;
}
else
{
#if GM_COMPILE_PASS_THIS_ALWAYS
a_byteCode->Emit(BC_PUSHTHIS);
#else // !GM_COMPILE_PASS_THIS_ALWAYS
// if the lvalue is a member, pass 'this', otherwise pass 'null'
bool pushed = false;
if(callee->m_type == CTNT_EXPRESSION && callee->m_subType == CTNET_IDENTIFIER)
{
gmCodeTreeVariableType vtype;
int offset = m_currentFunction->GetVariableOffset(callee->m_data.m_string, vtype);
if(((callee->m_flags & gmCodeTreeNode::CTN_MEMBER) > 0) || (offset == -1 && vtype == CTVT_MEMBER))
{
a_byteCode->Emit(BC_PUSHTHIS);
pushed = true;
}
}
if(!pushed)
{
a_byteCode->Emit(BC_PUSHNULL);
}
#endif // !GM_COMPILE_PASS_THIS_ALWAYS
}
if(!Generate(callee, a_byteCode)) return false;
}
// push parameters, count the number of parameters
gmuint32 numParams = 0;
const gmCodeTreeNode * params = a_node->m_children[1];
while(params)
{
++numParams;
if(!Generate(params, a_byteCode, false)) return false;
params = params->m_sibling;
}
// call
a_byteCode->Emit(BC_CALL, (gmuint32) numParams);
// restore the stack level.
a_byteCode->SetTos(stackLevel + 1);
return true;
}
示例12: GenExprOpAssign
bool gmCodeGenPrivate::GenExprOpAssign(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_OPERATION);
// value on left hand side must be an l-value... ie, a dot, array or identifier.
const gmCodeTreeNode * lValue = a_node->m_children[0];
int type = 0;
if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_OPERATION && lValue->m_subTypeType == CTNOT_DOT)
{
// Generate half l-value
if(!Generate(lValue->m_children[0], a_byteCode)) return false;
type = 0;
}
else if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_OPERATION && lValue->m_subTypeType == CTNOT_ARRAY_INDEX)
{
// Generate half l-value
if(!Generate(lValue->m_children[0], a_byteCode)) return false;
if(!Generate(lValue->m_children[1], a_byteCode)) return false;
type = 1;
}
else if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_IDENTIFIER)
{
type = 2;
}
else
{
if(m_log) m_log->LogEntry("error (%d) illegal l-value for '=' operator", a_node->m_lineNumber);
return false;
}
// Generate r-value
if(!Generate(a_node->m_children[1], a_byteCode)) return false;
// complete assignment
if(type == 0)
{
a_byteCode->EmitPtr(BC_SETDOT, m_hooks->GetSymbolId(lValue->m_children[1]->m_data.m_string));
}
else if(type == 1)
{
a_byteCode->Emit(BC_SETIND);
}
else if(type == 2)
{
gmCodeTreeVariableType vtype;
int offset = m_currentFunction->GetVariableOffset(lValue->m_data.m_string, vtype);
// if local, set local regardless
// if member set this
// if global, set global
// set and add local
if((lValue->m_flags & gmCodeTreeNode::CTN_MEMBER) > 0)
{
return a_byteCode->EmitPtr(BC_SETTHIS, m_hooks->GetSymbolId(lValue->m_data.m_string));
}
if(offset >= 0 && vtype == CTVT_LOCAL)
{
return a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
}
else if(offset == -1)
{
if(vtype == CTVT_MEMBER)
{
return a_byteCode->EmitPtr(BC_SETTHIS, m_hooks->GetSymbolId(lValue->m_data.m_string));
}
else if(vtype == CTVT_GLOBAL)
{
return a_byteCode->EmitPtr(BC_SETGLOBAL, m_hooks->GetSymbolId(lValue->m_data.m_string));
}
if(m_log) m_log->LogEntry("internal error");
return false;
}
offset = m_currentFunction->SetVariableType(lValue->m_data.m_string, CTVT_LOCAL);
return a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
}
else
{
// paranoia
if(m_log) m_log->LogEntry("internal error");
return false;
}
return true;
}
示例13: GenExprOpPreIncDec
bool gmCodeGenPrivate::GenExprOpPreIncDec(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_OPERATION);
// Make sure child 0 is an l-value
const gmCodeTreeNode * lValue = a_node->m_children[0];
int type = 0;
if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_OPERATION && lValue->m_subTypeType == CTNOT_DOT)
{
// Generate half l-value
if(!Generate(lValue->m_children[0], a_byteCode)) return false;
a_byteCode->Emit(BC_DUP);
a_byteCode->EmitPtr(BC_GETDOT, m_hooks->GetSymbolId(lValue->m_children[1]->m_data.m_string));
type = 0;
}
else if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_OPERATION && lValue->m_subTypeType == CTNOT_ARRAY_INDEX)
{
// Generate half l-value
if(!Generate(lValue->m_children[0], a_byteCode)) return false;
if(!Generate(lValue->m_children[1], a_byteCode)) return false;
a_byteCode->Emit(BC_DUP2);
a_byteCode->Emit(BC_GETIND);
type = 1;
}
else if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_IDENTIFIER)
{
if(!Generate(lValue, a_byteCode)) return false;
type = 2;
}
else
{
if(m_log) m_log->LogEntry("illegal l-value for '++/--' operator, line %d", a_node->m_lineNumber);
return false;
}
// Perform inc/dec
switch(a_node->m_subTypeType)
{
case CTNOT_PRE_INC : a_byteCode->Emit(BC_OP_INC); break;
case CTNOT_PRE_DEC : a_byteCode->Emit(BC_OP_DEC); break;
default :
{
if(m_log) m_log->LogEntry("unkown operator");
return false;
}
}
// Write back the value
if(type == 0)
{
int offset = m_currentFunction->SetVariableType(s_tempVarName0, CTVT_LOCAL);
a_byteCode->Emit(BC_DUP);
a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
a_byteCode->EmitPtr(BC_SETDOT, m_hooks->GetSymbolId(lValue->m_children[1]->m_data.m_string));
a_byteCode->Emit(BC_GETLOCAL, (gmuint32) offset);
}
else if(type == 1)
{
int offset = m_currentFunction->SetVariableType(s_tempVarName0, CTVT_LOCAL);
a_byteCode->Emit(BC_DUP);
a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
a_byteCode->Emit(BC_SETIND);
a_byteCode->Emit(BC_GETLOCAL, (gmuint32) offset);
}
else if(type == 2)
{
a_byteCode->Emit(BC_DUP);
gmCodeTreeVariableType vtype;
int offset = m_currentFunction->GetVariableOffset(lValue->m_data.m_string, vtype);
// if local, set local regardless
// if member set this
// if global, set global
// set and add local
if((lValue->m_flags & gmCodeTreeNode::CTN_MEMBER) > 0)
{
return a_byteCode->EmitPtr(BC_SETTHIS, m_hooks->GetSymbolId(lValue->m_data.m_string));
}
if(offset >= 0 && vtype == CTVT_LOCAL)
{
return a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
}
else if(offset == -1)
{
if(vtype == CTVT_MEMBER)
{
return a_byteCode->EmitPtr(BC_SETTHIS, m_hooks->GetSymbolId(lValue->m_data.m_string));
}
else if(vtype == CTVT_GLOBAL)
{
return a_byteCode->EmitPtr(BC_SETGLOBAL, m_hooks->GetSymbolId(lValue->m_data.m_string));
}
if(m_log) m_log->LogEntry("internal error");
return false;
}
offset = m_currentFunction->SetVariableType(lValue->m_data.m_string, CTVT_LOCAL);
//.........这里部分代码省略.........