将 armv7m 指令翻译成 LLVM IR

问题描述

我正在用 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

%r1 = 添加 i32 %r3,2

虽然我得到的输出是:

%12 = alloca i32,对齐 4

存储 i32 0,i32* %12,对齐 4

%r346 = 加载 i32,i32* %12,对齐 4

%r1 = 添加 i32 %r346,2

我可以在这里更新像 %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