【问题标题】:LLVM. How to access to struct fields based on their names?LLVM。如何根据名称访问结构字段?
【发布时间】:2013-07-01 16:24:09
【问题描述】:

我有很少的 C++ 示例代码:

struct RecordTest
{
    int value1;
    int value2;
};

void test()
{
    RecordTest rt;
    rt.value1 = 15;
    rt.value2 = 75;
}

和它的 LLVM 3.4 IR:

%struct.RecordTest = type { i32, i32 }

; Function Attrs: nounwind
define void @_Z4testv() #0 {
entry:
  %rt = alloca %struct.RecordTest, align 4
  %value1 = getelementptr inbounds %struct.RecordTest* %rt, i32 0, i32 0
  store i32 15, i32* %value1, align 4
  %value2 = getelementptr inbounds %struct.RecordTest* %rt, i32 0, i32 1
  store i32 75, i32* %value2, align 4
  ret void
}

还有一个非常简单的问题:如何访问RecordTest 字段(当我解析.cpp 时),没有索引,只有名称(value1 和value2)?

我只知道一种方式(来自llc -march=cpp)——使用索引:

  AllocaInst* ptr_rt = new AllocaInst(StructTy_struct_RecordTest, "rt", label_entry);
  ptr_rt->setAlignment(4);
  std::vector<Value*> ptr_value1_indices;
  ptr_value1_indices.push_back(const_int32_6);
  ptr_value1_indices.push_back(const_int32_6);
  Instruction* ptr_value1 = GetElementPtrInst::Create(ptr_rt, ptr_value1_indices, "value1", label_entry);
  StoreInst* void_9 = new StoreInst(const_int32_7, ptr_value1, false, label_entry);
  void_9->setAlignment(4);
  std::vector<Value*> ptr_value2_indices;
  ptr_value2_indices.push_back(const_int32_6);
  ptr_value2_indices.push_back(const_int32_5);
  Instruction* ptr_value2 = GetElementPtrInst::Create(ptr_rt, ptr_value2_indices, "value2", label_entry);
  StoreInst* void_10 = new StoreInst(const_int32_8, ptr_value2, false, label_entry);
  void_10->setAlignment(4);

那么,如果我不知道字段的索引(上面代码中的const_int32_5 和const_int32_6),我可以从 C++ 转换为 LLVM IR 吗?

UPD=================================

因此,我们无法访问字段名称。如果我们需要它(我们确实需要,如果我们解析 .cpp), 我们可以这样写:

 // It can be some kind of singletone
static std::map<std::string, std::vector<std::string>> mymap;

// Some function, where we first time meet RecordTest
    std::vector<std::string> fieldNames;
    fieldNames.push_back("value1");
    fieldNames.push_back("value2");
    mymap["RecordTest"] = fieldNames;

// Some function, where we need to access to RecordTest field
    std::vector<std::string> fieldNamesAgain = mymap.find("RecordTest")->second;
    std::string fieldName = "value1";
    int idxValue1 = -1;
    for (int i = 0, e = fieldNamesAgain.size(); i < e; i++) // little ugly search
    {
        if (fieldName == fieldNamesAgain[i])
        {
                // we get field index, and now we can build code
                // as in example above (llc -march=cpp)
            idxValue1 = i;  
            break;
        }
    }

这样对吗?

【问题讨论】:

    标签: llvm llvm-c++-api


    【解决方案1】:

    您不能通过名称访问结构的字段,只能通过索引访问。当您使用 Clang 编译时,这些信息通常不存在。

    有一个例外,那就是如果您使用调试信息进行编译。在这种情况下,您将获得有关该类型的大量数据;具体来说,您将获得字段的顺序,以及每个字段的元数据条目,其中包含其名称(以及其他有用的东西,例如它与类型开头的偏移量)。

    在 Source Level Debugging 指南上阅读更多相关信息 - 特别是,请参阅 this section about struct encoding 及其非常好的示例。

    查看DebugInfo.h 以获取有助于查询调试信息的类,但我认为无论如何您都必须进行一些手动挖掘。

    【讨论】:

    • 谢谢!那么,在这种情况下,我应该如何在没有调试信息的情况下访问这些字段?我已经更新了问题,如果您有一点空闲时间,请看一下。
    • @kpdev 我不明白,你首先将如何填充mymap?我的意思是,如果没有调试信息,您将从哪里获得有关其字段的信息?
    • 来自解析 .cpp 文件。 (或其他语言的源文件——例如,我为 Oberon 风格的语言编写了一个 LLVM 编译器)。我们可以在这一步填充 mymap(为每个新结构获取对字段索引)
    • @kpdev 如果您使用的是 Clang,更好的解决方案是使用调试符号进行编译。如果您使用的不是 Clang,而是您自己的前端,那么是的,正确的方法是在解析期间将数据编码为 LLVM metadata(另请参阅 this blog post),然后您可以从 LLVM 中提取它。
    • 是的,我正在使用自己的前端(实际上是我编写的)。感谢您提供链接,我会立即查看)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2014-07-13
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多