问题描述
我正在用 C++ 开发一个提升器,将 armv7m 指令提升到 LLVM IR。
现在我处于翻译阶段,我只需输入一条 arm 指令并将其翻译成等效的 SSA LLVM IR 指令。
我的架构只是为汇编代码中的每个函数创建一个 llvm 函数,并为函数内的每个基本块创建一个 llvm 基本块,对于基本块内的每个汇编指令,我使用构建器构建等效的 llvm IR 指令对于该指令(同时将该指令的基本块的 llvm 基本块传递给 IRBuilder)。我的 ADD 汇编指令代码示例。
//Translates an ADD assembly instruction object into the equivalent SSA llvm IR instructions.
llvm::Instruction* ADD(Instr* instruction,bool update_condition_flags = false) {
IRBuilder<> builder(instruction->basic_block->get_llvm_basic_block());
std::vector<Reg*> registers = instruction->get_registers();
std::vector<Immediate*> immediates = instruction->get_immediates();
if (instruction->get_immediates().empty()) {
std::string register1 = registers[1]->get_register_name();
Value* register1_val = registers[1]->get_register_value();
llvm::Value* immediate = immediates[0]->get_immediate_value_long();
std::string output_register = registers[0]->get_register_name();
llvm::Instruction* x = builder.Createalloca(Type::getInt32Ty(TheContext),nullptr);
instruction->insert_llvm_instructions(x);
llvm::Instruction* s = builder.CreateStore(register1_val,x,/*isVolatile=*/false);
instruction->insert_llvm_instructions(s);
llvm::Instruction* LHS = builder.CreateLoad(x,register1);
instruction->insert_llvm_instructions(LHS);
llvm::Instruction* add_ll = BinaryOperator::Create(Instruction::Add,LHS,immediate,output_register);
instruction->insert_llvm_instructions(add_ll);
return add_ll;
基本上,我正在尝试为示例 add r1,r3,#2
汇编指令生成 llvm IR 指令。
我想在生成的等效 llvm ir 指令(即 %r1,%r3)中使用汇编指令 (r1,r3) 中使用的寄存器的名称。但是,在生成的 IR 中的许多实例中,我在该示例中将额外的索引添加到寄存器名称中,作为 %r346(在“%r3”之后添加了“46”)。为什么要添加这些索引,有没有办法删除它们。
例如 add r1,#2
汇编指令。我想要的输出是:
%12 = alloca i32,对齐 4
存储 i32 0,i32* %12,对齐 4
%r3 = 加载 i32,i32* %12,对齐 4
虽然我得到的输出是:
%12 = alloca i32,对齐 4
存储 i32 0,i32* %12,对齐 4
%r346 = 加载 i32,i32* %12,对齐 4
我可以在这里更新像 %1 这样的 llvm 函数中的变量吗?
%1 = mul i32 %x,%y
%1 = 添加 i32 %1,%z
当我测试我的 Lifter id 时,我喜欢跟随一个特定的寄存器 (r3),因为它通过函数内的不同汇编指令进行。而这些额外的索引会增加混乱。对于以下汇编代码 id,例如为每个汇编指令生成的 llvm IR 具有 %r3 没有任何附加索引。
ldr r3,[fp,#-8]
add r3,#1
str r3,#-8]
解决方法
LLVM IR 使用 SSA,即。每个符号仅指一个值。 add r3,r3,#1
是不可能的,因为 r3 指的是两个值(结果和输入)。
我认为最常见的解决方案是添加一个后缀,您可以根据函数内的偏移量确定该后缀。如果 add 是第 16 条指令,而它使用的 r3 来自第 12 条指令,则可能是 %r3.16 = add i32 %r3.12,1
。