• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C++ llvm::Function类代码示例

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本文整理汇总了C++中llvm::Function的典型用法代码示例。如果您正苦于以下问题:C++ Function类的具体用法?C++ Function怎么用?C++ Function使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。



在下文中一共展示了Function类的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。

示例1: runOnFunction

bool IndependentBlocks::runOnFunction(llvm::Function &F) {

  bool Changed = false;

  RI = &getAnalysis<RegionInfoPass>().getRegionInfo();
  LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
  SD = &getAnalysis<ScopDetection>();
  SE = &getAnalysis<ScalarEvolution>();

  AllocaBlock = &F.getEntryBlock();

  DEBUG(dbgs() << "Run IndepBlock on " << F.getName() << '\n');

  for (const Region *R : *SD) {
    Changed |= createIndependentBlocks(R);
    Changed |= eliminateDeadCode(R);
    // This may change the RegionTree.
    if (!DisableIntraScopScalarToArray || !PollyModelPHINodes)
      Changed |= splitExitBlock(const_cast<Region *>(R));
  }

  DEBUG(dbgs() << "Before Scalar to Array------->\n");
  DEBUG(F.dump());

  if (!DisableIntraScopScalarToArray || !PollyModelPHINodes)
    for (const Region *R : *SD)
      Changed |= translateScalarToArray(R);

  DEBUG(dbgs() << "After Independent Blocks------------->\n");
  DEBUG(F.dump());

  verifyAnalysis();

  return Changed;
}
开发者ID:larryv,项目名称:polly,代码行数:35,代码来源:IndependentBlocks.cpp


示例2: incrementFunctionVersion

void md::incrementFunctionVersion(llvm::Function &fn)
{
	unsigned newVersion = getFunctionVersion(fn) + 1;
	auto& ctx = fn.getContext();
	ConstantInt* cNewVersion = ConstantInt::get(Type::getInt32Ty(ctx), newVersion);
	MDNode* versionNode = MDNode::get(ctx, ConstantAsMetadata::get(cNewVersion));
	fn.setMetadata("fcd.funver", versionNode);
}
开发者ID:Trass3r,项目名称:fcd,代码行数:8,代码来源:metadata.cpp


示例3: shouldIgnoreFunction

bool DINOGlobal::shouldIgnoreFunction (const llvm::Function &F) {
    if (F.getName().find(DINOPrefix) == 0) {

#ifdef DINO_VERBOSE
        llvm::outs() << "Skipping DINO function " << F.getName() << "\n";
#endif //DINO_VERBOSE

        return true;
    }
    return false;
}
开发者ID:blucia0a,项目名称:dino,代码行数:11,代码来源:DINO.cpp


示例4: InspectFunction

    //------------------------------------------------------------------
    /// Scan a function to see if any instructions are interesting
    ///
    /// @param[in] f
    ///     The function to be inspected.
    ///
    /// @return
    ///     False if there was an error scanning; true otherwise.
    //------------------------------------------------------------------
    virtual bool InspectFunction(llvm::Function &f)
    {
        for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
             bbi != last_bbi;
             ++bbi)
        {
            if (!InspectBasicBlock(*bbi))
                return false;
        }

        return true;
    }
开发者ID:Aj0Ay,项目名称:lldb,代码行数:21,代码来源:IRDynamicChecks.cpp


示例5: runOnFunction

void AstBackEnd::runOnFunction(llvm::Function& fn)
{
	grapher.reset(new AstGrapher);
	
	// Before doing anything, create statements for blocks in reverse post-order. This ensures that values exist
	// before they are used. (Post-order would try to use statements before they were created.)
	for (BasicBlock* block : ReversePostOrderTraversal<BasicBlock*>(&fn.getEntryBlock()))
	{
		grapher->createRegion(*block, *output->basicBlockToStatement(*block));
	}
	
	// Identify loops, then visit basic blocks in post-order. If the basic block if the head
	// of a cyclic region, process the loop. Otherwise, if the basic block is the start of a single-entry-single-exit
	// region, process that region.
	
	auto& domTreeWrapper = getAnalysis<DominatorTreeWrapperPass>(fn);
	domTree = &domTreeWrapper.getDomTree();
	postDomTree->recalculate(fn);
	RootedPostDominatorTree::treeFromIncompleteTree(fn, postDomTree);
	
	// Traverse graph in post-order. Try to detect regions with the post-dominator tree.
	// Cycles are only considered once.
	for (BasicBlock* entry : post_order(&fn.getEntryBlock()))
	{
		BasicBlock* postDominator = entry;
		while (postDominator != nullptr)
		{
			AstGraphNode* graphNode = grapher->getGraphNodeFromEntry(postDominator);
			BasicBlock* exit = graphNode->hasExit()
				? graphNode->getExit()
				: postDominatorOf(*postDomTree, *postDominator);
			
			RegionType region = isRegion(*entry, exit);
			if (region == Acyclic)
			{
				runOnRegion(fn, *entry, exit);
			}
			else if (region == Cyclic)
			{
				runOnLoop(fn, *entry, exit);
			}
			
			if (!domTree->dominates(entry, exit))
			{
				break;
			}
			postDominator = exit;
		}
	}
	
	Statement* bodyStatement = grapher->getGraphNodeFromEntry(&fn.getEntryBlock())->node;
	output->setBody(bodyStatement);
}
开发者ID:Lukas-Dresel,项目名称:fcd,代码行数:53,代码来源:pass_backend.cpp


示例6: while

bool BitcastCallEliminator::runOnFunction(llvm::Function &function)
{
    bool res = false;
    bool doLoop = true;
    while (doLoop) {
        doLoop = false;
        for (llvm::Function::iterator i = function.begin(), e = function.end(); i != e; ++i) {
            llvm::BasicBlock *bb = &*i;
            bool bbchanged = false;
            for (llvm::BasicBlock::iterator ibb = bb->begin(), ebb = bb->end(); ibb != ebb; ++ibb) {
                llvm::Instruction *inst = &*ibb;
                if (llvm::isa<llvm::CallInst>(inst) && llvm::cast<llvm::CallInst>(inst)->getCalledFunction() == NULL) {
                    llvm::CallInst *callInst = llvm::cast<llvm::CallInst>(inst);
                    llvm::Value *calledValue = callInst->getCalledValue();
                    llvm::Value *bareCalledValue = calledValue->stripPointerCasts();
                    if (llvm::isa<llvm::Function>(bareCalledValue)) {
                        const llvm::FunctionType *calledType = llvm::cast<llvm::FunctionType>(llvm::cast<llvm::PointerType>(calledValue->getType())->getContainedType(0));
                        const llvm::FunctionType *calleeType = llvm::cast<llvm::Function>(bareCalledValue)->getFunctionType();
                        if (calledType->getReturnType() == calleeType->getReturnType()) {
                            if (argsMatch(calleeType, callInst)) {
                                std::vector<llvm::Value*> args;
                                unsigned int numArgs = callInst->getNumArgOperands();
                                for (unsigned int k = 0; k < numArgs; ++k) {
                                    args.push_back(callInst->getArgOperand(k));
                                }
#if LLVM_VERSION < VERSION(3, 0)
                                llvm::CallInst *newCall = llvm::CallInst::Create(bareCalledValue, args.begin(), args.end(), "", inst);
#else
                                llvm::CallInst *newCall = llvm::CallInst::Create(bareCalledValue, args, "", inst);
#endif
                                inst->replaceAllUsesWith(newCall);
                                llvm::StringRef name = inst->getName();
                                inst->eraseFromParent();
                                newCall->setName(name);
                                res = true;
                                doLoop = true;
                                bbchanged = true;
                            }
                        }
                    }
                }
                if (bbchanged) {
                    break;
                }
            }
        }
    }
    return res;
}
开发者ID:jeroenk,项目名称:llvm2kittel,代码行数:49,代码来源:BitcastCallEliminator.cpp


示例7: runOnFunction

bool InstructionCount::runOnFunction(llvm::Function &Fun) {
  ICount = 0;

  // A llvm::Function is just a list of llvm::BasicBlock. In order to get
  // instruction count we can visit all llvm::BasicBlocks ...
  for(llvm::Function::const_iterator I = Fun.begin(),
                                     E = Fun.end();
                                     I != E;
                                     ++I)
    // ... and sum the llvm::BasicBlock size -- A llvm::BasicBlock size is just
    // a list of instructions!
    ICount += I->size();

  return false;
}
开发者ID:michele-scandale,项目名称:COTPasses,代码行数:15,代码来源:InstructionCount.cpp


示例8: runOnFunction

bool Unboxing::runOnFunction(llvm::Function & f) {
    //std::cout << "running Unboxing optimization..." << std::endl;
    m = reinterpret_cast<RiftModule*>(f.getParent());
    ta = &getAnalysis<TypeAnalysis>();
    for (auto & b : f) {
        auto i = b.begin();
        while (i != b.end()) {
            ins = i;
            bool erase = false;
            if (CallInst * ci = dyn_cast<CallInst>(ins)) {
                StringRef s = ci->getCalledFunction()->getName();
                if (s == "genericAdd") {
                    erase = genericArithmetic(Instruction::FAdd);
                } else if (s == "genericSub") {
                    erase = genericArithmetic(Instruction::FSub);
                } else if (s == "genericMul") {
                    erase = genericArithmetic(Instruction::FMul);
                } else if (s == "genericDiv") {
                    erase = genericArithmetic(Instruction::FDiv);
                } else if (s == "genericLt") {
                    erase = genericRelational(FCmpInst::FCMP_OLT);
                } else if (s == "genericGt") {
                    erase = genericRelational(FCmpInst::FCMP_OGT);
                } else if (s == "genericEq") {
                    erase = genericRelational(FCmpInst::FCMP_OEQ);
                } else if (s == "genericNeq") {
                    erase = genericRelational(FCmpInst::FCMP_ONE);
                } else if (s == "genericGetElement") {
                    erase = genericGetElement();
                }
            }
            if (erase) {
                llvm::Instruction * v = i;
                ++i;
                state().erase(v);
                v->eraseFromParent();
            } else {
                ++i;
            }
        }
    }
    if (DEBUG) {
        cout << "After unboxing optimization: --------------------------------" << endl;
        f.dump();
        state().print(cout);
    }
    return false;
}
开发者ID:janvitek,项目名称:rift,代码行数:48,代码来源:unboxing.cpp


示例9: runOnFunction

		bool CLIPSFunctionPass::runOnFunction(llvm::Function& function) {
			if(!function.isDeclaration()) {
				void* env = getEnvironment();
				CLIPSEnvironment* clEnv = new CLIPSEnvironment(env);
				EnvReset(env);
				CLIPSPassHeader* header = (CLIPSPassHeader*)getIndirectPassHeader();
				char* passes = CharBuffer(strlen(header->getPasses()) + 64);
				sprintf(passes,"(passes %s)", header->getPasses());
				EnvAssertString(env, passes);
				free(passes);
				KnowledgeConstructor tmp;
				if(header->needsLoops() && header->needsRegions()) {
					llvm::LoopInfo& li = getAnalysis<LoopInfo>();
					llvm::RegionInfo& ri = getAnalysis<RegionInfo>();
					tmp.route(function, li, ri);
				} else if(header->needsLoops() && !header->needsRegions()) {
					llvm::LoopInfo& li = getAnalysis<LoopInfo>();
					tmp.route(function, li);
				} else if(header->needsRegions() && !header->needsLoops()) {
					llvm::RegionInfo& ri = getAnalysis<RegionInfo>();
					tmp.route(function, ri);
				} else {
					tmp.route(function);
				}
				clEnv->makeInstances((char*)tmp.getInstancesAsString().c_str());
				//TODO: put in the line to build the actual knowledge
				EnvRun(env, -1L);
				//it's up to the code in the expert system to make changes
				EnvReset(env);
				return true;
			} else {
				return false;
			}
		}
开发者ID:DrItanium,项目名称:durandal,代码行数:34,代码来源:CLIPSPassTemplates.cpp


示例10: runOnFunction

bool ArgumentRenamePass::runOnFunction(llvm::Function &F) {
  for (auto &A : F.args()) {
    A.setName("arg." + A.getName());
  }

  return true;
}
开发者ID:mc-imperial,项目名称:bugle,代码行数:7,代码来源:ArgumentRenamePass.cpp


示例11: runOnFunction

bool BasicFunctionPass::runOnFunction(llvm::Function& function) {
  RemoveRedundantCallsToSetVisibility optimize_set_visibility;
  bool changed = false;
  for (auto& block : function.getBasicBlockList()) {
    bool block_changed = optimize_set_visibility.runOnBasicBlock(block);
    changed = changed || block_changed;
  }
  return changed;
}
开发者ID:kmillar,项目名称:rho,代码行数:9,代码来源:Optimization.cpp


示例12: emitValidRemarks

void emitValidRemarks(const llvm::Function &F, const Region *R) {
  LLVMContext &Ctx = F.getContext();

  DebugLoc Begin, End;
  getDebugLocations(R, Begin, End);

  emitOptimizationRemark(Ctx, DEBUG_TYPE, F, Begin,
                         "A valid Scop begins here.");
  emitOptimizationRemark(Ctx, DEBUG_TYPE, F, End, "A valid Scop ends here.");
}
开发者ID:mbdharan,项目名称:polly,代码行数:10,代码来源:ScopDetectionDiagnostic.cpp


示例13: visitBasicBlock

std::vector<llvm::BasicBlock*> BasicBlockSorter::sortBasicBlocks(llvm::Function &function)
{
    std::vector<llvm::BasicBlock*> ret;
    std::set<llvm::BasicBlock*> visited;

    llvm::BasicBlock &entryBlock = function.getEntryBlock();

    visitBasicBlock(ret, visited, &entryBlock);

    return ret;
}
开发者ID:hkhlaaf,项目名称:llvm2kittel,代码行数:11,代码来源:BasicBlockSorter.cpp


示例14: createPrimitiveDestructor

void createPrimitiveDestructor(Module& module, const SEM::TypeInstance* const typeInstance, llvm::Function& llvmFunction) {
    assert(llvmFunction.isDeclaration());

    Function functionGenerator(module, llvmFunction, destructorArgInfo(module, *typeInstance), &(module.templateBuilder(TemplatedObject::TypeInstance(typeInstance))));

    const auto debugInfo = genDebugDestructorFunction(module, *typeInstance, &llvmFunction);
    functionGenerator.attachDebugInfo(debugInfo);
    functionGenerator.setDebugPosition(getDebugDestructorPosition(module, *typeInstance));

    genPrimitiveDestructorCall(functionGenerator, typeInstance->selfType(), functionGenerator.getRawContextValue());
    functionGenerator.getBuilder().CreateRetVoid();

    functionGenerator.verify();
}
开发者ID:PuerkitoBio,项目名称:locic,代码行数:14,代码来源:PrimitiveDestructor.cpp


示例15: useEntryBuilder

		Function::Function(Module& pModule, llvm::Function& function, const ArgInfo& argInfo, TemplateBuilder* pTemplateBuilder)
			: module_(pModule), function_(function),
			  entryBuilder_(pModule.getLLVMContext()),
			  builder_(pModule.getLLVMContext()),
			  createdEntryBlock_(false),
			  useEntryBuilder_(false),
			  argInfo_(argInfo),
			  templateBuilder_(pTemplateBuilder),
#if LOCIC_LLVM_VERSION < 307
			  debugInfo_(nullptr),
#endif
			  exceptionInfo_(nullptr),
			  returnValuePtr_(nullptr),
			  templateArgs_(nullptr),
			  unwindState_(nullptr) {
			assert(function.isDeclaration());
			assert(argInfo_.numArguments() == function_.getFunctionType()->getNumParams());
			
			// Add a bottom level unwind stack.
			unwindStackStack_.push(UnwindStack());
			
			// Add bottom level action for this function.
			unwindStack().push_back(UnwindAction::FunctionMarker());
			
			const auto startBB = createBasicBlock("");
			builder_.SetInsertPoint(startBB);
			
			argValues_.reserve(function_.arg_size());
			
			for (auto arg = function_.arg_begin(); arg != function_.arg_end(); ++arg) {
				argValues_.push_back(arg);
			}
			
			std::vector<llvm_abi::Type*> argABITypes;
			argABITypes.reserve(argInfo.argumentTypes().size());
			
			std::vector<llvm::Type*> argLLVMTypes;
			argLLVMTypes.reserve(argInfo.argumentTypes().size());
			
			for (const auto& typePair : argInfo.argumentTypes()) {
				argABITypes.push_back(typePair.first);
				argLLVMTypes.push_back(typePair.second);
			}
			
			SetUseEntryBuilder useEntryBuilder(*this);
			// Decode arguments according to ABI.
			decodeABIValues(argValues_, argABITypes, argLLVMTypes);
		}
开发者ID:PuerkitoBio,项目名称:locic,代码行数:48,代码来源:Function.cpp


示例16: runOnFunction

bool FunctionEraser::runOnFunction(llvm::Function &Fun) {
  // Get the analysis we need. Please notice that we are not giving any argument
  // to 'getAnalysis'. This is the correct way for requesting analysis from
  // 'llvm::FunctionPass'. If you need to get analysis information from a
  // 'llvm::ModulePass', then you have to give the Function you want to analyze
  // as 'getAnalysis' argument.
  InstructionCount &ICount = getAnalysis<InstructionCount>();

  if(ICount.GetInstructionCount() < EraseThreshold)
    return false;

  // Apply the transformation by erasing function body.
  Fun.deleteBody();

  // Update pass statistics.
  ++ErasedFunctions;

  return true;
}
开发者ID:michele-scandale,项目名称:COTPasses,代码行数:19,代码来源:FunctionEraser.cpp


示例17: runOnFunction

bool MemoryAnalyzer::runOnFunction(llvm::Function &function)
{
    m_globals.clear();
    m_map.clear();
    m_mayZap.clear();
    llvm::Module *module = function.getParent();
    for (llvm::Module::global_iterator global = module->global_begin(), globale = module->global_end(); global != globale; ++global) {
        const llvm::Type *globalType = llvm::cast<llvm::PointerType>(global->getType())->getContainedType(0);
        if (llvm::isa<llvm::IntegerType>(globalType)) {
            m_globals.insert(&*global);
        }
    }
#if LLVM_VERSION < VERSION(3, 8)
    m_aa = &getAnalysis<llvm::AliasAnalysis>();
#else
    m_aa = &getAnalysis<llvm::AAResultsWrapperPass>().getAAResults();
#endif
    visit(function);
    return false;
}
开发者ID:jeroenk,项目名称:llvm2kittel,代码行数:20,代码来源:MemoryAnalyzer.cpp


示例18: emitRejectionRemarks

void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log) {
  LLVMContext &Ctx = F.getContext();

  const Region *R = Log.region();
  DebugLoc Begin, End;

  getDebugLocations(R, Begin, End);

  emitOptimizationRemarkMissed(
      Ctx, DEBUG_TYPE, F, Begin,
      "The following errors keep this region from being a Scop.");

  for (RejectReasonPtr RR : Log) {
    if (const DebugLoc &Loc = RR->getDebugLoc())
      emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Loc,
                                   RR->getEndUserMessage());
  }

  emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, End,
                               "Invalid Scop candidate ends here.");
}
开发者ID:mbdharan,项目名称:polly,代码行数:21,代码来源:ScopDetectionDiagnostic.cpp


示例19: optimizeFunction

void JITEngine::optimizeFunction(llvm::Function &f) {
    f.viewCFG();
    m_llvmFuncPassManager->run(f);
    f.viewCFG();
}
开发者ID:cpichard,项目名称:fission,代码行数:5,代码来源:JITEngine.cpp


示例20: analyzeFunction

bool CallingConvention_AnyArch_AnyCC::analyzeFunction(ParameterRegistry &registry, CallInformation &fillOut, llvm::Function &func)
{
	if (!isFullDisassembly() || md::isPrototype(func))
	{
		return false;
	}
	
	auto regs = &*func.arg_begin();
	unordered_map<const TargetRegisterInfo*, ModRefInfo> resultMap;
	
	// Find all GEPs
	const auto& target = registry.getTargetInfo();
	unordered_multimap<const TargetRegisterInfo*, User*> registerUsers;
	for (User* user : regs->users())
	{
		if (const TargetRegisterInfo* maybeRegister = target.registerInfo(*user))
		{
			const TargetRegisterInfo& registerInfo = target.largestOverlappingRegister(*maybeRegister);
			registerUsers.insert({&registerInfo, user});
		}
	}
	
	// Find all users of these GEPs
	DominatorsPerRegister gepUsers;
	for (auto iter = registerUsers.begin(); iter != registerUsers.end(); iter++)
	{
		addAllUsers(*iter->second, iter->first, gepUsers);
	}
	
	DominatorTree& preDom = registry.getAnalysis<DominatorTreeWrapperPass>(func).getDomTree();
	PostDominatorTree& postDom = registry.getAnalysis<PostDominatorTreeWrapperPass>(func).getPostDomTree();
	
	// Add calls
	SmallVector<CallInst*, 8> calls;
	CallGraph& cg = registry.getAnalysis<CallGraphWrapperPass>().getCallGraph();
	CallGraphNode* thisFunc = cg[&func];
	for (const auto& pair : *thisFunc)
	{
		Function* callee = pair.second->getFunction();
		if (const CallInformation* callInfo = registry.getCallInfo(*callee))
		if (callInfo->getStage() == CallInformation::Completed)
		{
			// pair.first is a weak value handle and has a cast operator to get the pointee
			CallInst* caller = cast<CallInst>((Value*)pair.first);
			calls.push_back(caller);
			
			for (const auto& vi : *callInfo)
			{
				if (vi.type == ValueInformation::IntegerRegister)
				{
					gepUsers[vi.registerInfo].insert(caller);
				}
			}
		}
	}
	
	// Start out resultMap based on call dominance. Weed out calls until dominant call set has been established.
	// This map will be refined by results from mod/ref instruction analysis. The purpose is mainly to define
	// mod/ref behavior for registers that are used in callees of this function, but not in this function
	// directly.
	while (calls.size() > 0)
	{
		unordered_map<const TargetRegisterInfo*, unsigned> callResult;
		auto dominant = findDominantValues(preDom, calls);
		for (CallInst* call : dominant)
		{
			Function* callee = call->getCalledFunction();
			for (const auto& pair : translateToModRef(*registry.getCallInfo(*callee)))
			{
				callResult[pair.first] |= pair.second;
			}
			
			calls.erase(find(calls.begin(), calls.end(), call));
		}
		
		for (const auto& pair : callResult)
		{
			resultMap[pair.first] = static_cast<ModRefInfo>(pair.second);
		}
	}
	
	// Find the dominant use(s)
	auto preDominatingUses = gepUsers;
	for (auto& pair : preDominatingUses)
	{
		pair.second = findDominantValues(preDom, pair.second);
	}
	
	// Fill out ModRef use dictionary
	// (Ref info is incomplete)
	for (auto& pair : preDominatingUses)
	{
		ModRefInfo& r = resultMap[pair.first];
		r = IncompleteRef;
		for (auto inst : pair.second)
		{
			if (isa<StoreInst>(inst))
			{
				// If we see a dominant store, then the register is modified.
				r = MRI_Mod;
//.........这里部分代码省略.........
开发者ID:Trass3r,项目名称:fcd,代码行数:101,代码来源:anyarch_anycc.cpp



注:本文中的llvm::Function类示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C++ llvm::MCInst类代码示例发布时间:2022-05-31
下一篇:
C++ llvm::FoldingSetNodeID类代码示例发布时间:2022-05-31
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap