IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> PHINode通用移除方法 -> 正文阅读

[移动开发]PHINode通用移除方法

具体PHINode->getNumIncomingValues(i),的value用放在一个store和load替换放在PHINode的出口处

/**
 * @file src/bin2llvmir/optimizations/phi_remover/phi_remover.cpp
 * @brief Remove all Phi nodes (instructions).
 * @copyright (c) 2017 Avast Software, licensed under the MIT license
 */

#include <llvm/IR/InstIterator.h>
#include <llvm/IR/Instructions.h>

#include <llvm/Transforms/Utils/Local.h>

#include "retdec/bin2llvmir/optimizations/phi_remover/phi_remover.h"
#include "retdec/bin2llvmir/providers/asm_instruction.h"

namespace retdec {
namespace bin2llvmir {

char PhiRemover::ID = 0;

static llvm::RegisterPass<PhiRemover> X(
		"retdec-remove-phi",
		"Phi removal",
		 false, // Only looks at CFG
		 false // Analysis Pass
);

PhiRemover::PhiRemover() :
		ModulePass(ID)
{

}

bool PhiRemover::runOnModule(llvm::Module& M)
{
	_module = &M;
	_config = ConfigProvider::getConfig(_module);
	return run();
}

bool PhiRemover::runOnModuleCustom(llvm::Module& M, Config* c)
{
	_module = &M;
	_config = c;
	return run();
}

common::Address getInstAddress(const llvm::Instruction *i)
{
	if (llvm::MDNode* mdn = i->getMetadata("insn.addr"))
	{
		llvm::ConstantInt* CI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
			mdn->getOperand(0));
		return CI->getZExtValue();
	}

	return common::Address::Undefined;
}

llvm::MDNode* getInstAddressMeta(common::Address a, llvm::Module* m)
{
	return llvm::MDNode::get(
		m->getContext(),
		llvm::ValueAsMetadata::get(llvm::ConstantInt::get(
			llvm::Type::getInt64Ty(m->getContext()),
			a,
			false
		))
	);
}

/**
 * @return @c True if at least one instruction was removed.
 *         @c False otherwise.
 */
bool PhiRemover::run()
{
	bool changed = false;

	for (llvm::Function& f : *_module)
	{
		if (f.isDeclaration())
		{
			continue;
		}

		auto faddr = _config->getFunctionAddress(&f);
		llvm::MDNode* fmeta = nullptr;

		auto* entryBb = &f.getEntryBlock();
		llvm::BasicBlock::iterator insertIt = entryBb->begin();
		while (llvm::isa<llvm::AllocaInst>(insertIt))
		{
			++insertIt;
		}

		for (auto it = llvm::inst_begin(&f), eIt = llvm::inst_end(&f); it != eIt;)
		{
			llvm::Instruction* insn = &*it;
			++it;

			if (auto* phi = llvm::dyn_cast<llvm::PHINode>(insn))
			{
				if (fmeta == nullptr)
				{
					fmeta = getInstAddressMeta(faddr, _module);
				}

				changed |= demotePhiToStack(phi, fmeta);
			}
		}
	}

	return changed;
}

/**
 * Code taken from llvm::DemotePHIToStack().
 * We need to implement it ourselves in order to add instruction
 * address metadata to newly created instructions.
 */
bool PhiRemover::demotePhiToStack(
		llvm::PHINode* phi,
		llvm::MDNode* faddr)
{
	if (phi->use_empty())
	{
		phi->eraseFromParent();
		return true;
	}

	const llvm::DataLayout& DL = phi->getModule()->getDataLayout();

	// Create a stack slot to hold the value.
	llvm::Function *F = phi->getParent()->getParent();
	auto* alloca = new llvm::AllocaInst(
			phi->getType(),
			DL.getAllocaAddrSpace(),
			nullptr,
			phi->getName() + ".reg2mem",
			&F->getEntryBlock().front()
	);
	alloca->setMetadata("insn.addr", faddr);

	// Iterate over each operand inserting a store in each predecessor.
	for (unsigned i = 0, e = phi->getNumIncomingValues(); i < e; ++i)
	{
		if (auto *II = llvm::dyn_cast<llvm::InvokeInst>(phi->getIncomingValue(i)))
		{
			assert(II->getParent() != phi->getIncomingBlock(i) &&
			"Invoke edge not supported yet"); (void)II;
		}
		auto* insertInsn = phi->getIncomingBlock(i)->getTerminator();
		auto a = getInstAddress(insertInsn);
		auto* s = new llvm::StoreInst(
				phi->getIncomingValue(i),
				alloca,
				insertInsn);
		if (a.isDefined())
		{
			s->setMetadata("insn.addr", getInstAddressMeta(a, _module));
		}
	}

	// Insert a load in place of the PHI and replace all uses.
	llvm::BasicBlock::iterator InsertPt = phi->getIterator();

	for (; llvm::isa<llvm::PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt)
	/* empty */;   // Don't insert before PHI nodes or landingpad instrs.

	auto a = getInstAddress(phi);
	auto* l = new llvm::LoadInst(
			alloca,
			phi->getName() + ".reload",
			&*InsertPt);
	if (a.isDefined())
	{
		l->setMetadata("insn.addr", getInstAddressMeta(a, _module));
	}
	phi->replaceAllUsesWith(l);

	// Delete PHI.
	phi->eraseFromParent();
	return alloca;
}

} // namespace bin2llvmir
} // namespace retdec

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:39:08  更:2022-03-08 22:40:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 16:47:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码