解析数据结构clang/LLVM

解析数据结构clang/LLVM,clang,llvm,llvm-clang,llvm-ir,Clang,Llvm,Llvm Clang,Llvm Ir,我想知道从C源文件解析和获取数据结构的最佳解决方案是什么。假设我有: typedef int M_Int; typedef float* P_Float; typedef struct Foo { M_Int a; P_Float p_f; } Foo; 为了获得structFoo的变量a和p\f的原语,展开数据结构的最佳方式是什么 对于非常简单的示例,解析AST可能是最好的方法,但是当代码变得更复杂时,也许最好以更低级的方式使用IR代码?您可以使用llvm debug info获取

我想知道从C源文件解析和获取数据结构的最佳解决方案是什么。假设我有:

typedef int M_Int;
typedef float* P_Float;

typedef struct Foo {
  M_Int a;
  P_Float p_f;
} Foo;
为了获得struct
Foo
的变量
a
p\f
的原语,展开数据结构的最佳方式是什么


对于非常简单的示例,解析AST可能是最好的方法,但是当代码变得更复杂时,也许最好以更低级的方式使用IR代码?

您可以使用llvm debug info获取所需的信息。如果使用
-g
选项编译C代码,它将生成包含所有信息的调试信息。理解llvm debuginfo非常棘手,因为没有太多关于它们的结构和如何访问它们的文档。以下是一些链接:

(一)


2) 下面是我正在处理的一个使用调试信息的项目的链接。这可能不会太有用,因为没有太多文档,但是查看debuginfo类的用法可能会很有用。我们试图为C函数的所有指针参数(包括结构参数的字段名)获取字段名。与debuginfo访问相关的所有代码都在这个文件中:

您可以使用llvm debug info获取所需的信息。如果使用
-g
选项编译C代码,它将生成包含所有信息的调试信息。理解llvm debuginfo非常棘手,因为没有太多关于它们的结构和如何访问它们的文档。以下是一些链接:

(一)


2) 下面是我正在处理的一个使用调试信息的项目的链接。这可能不会太有用,因为没有太多文档,但是查看debuginfo类的用法可能会很有用。我们试图为C函数的所有指针参数(包括结构参数的字段名)获取字段名。与debuginfo访问相关的所有代码都在这个文件中:

要查找底层类型,AST是一个很好的工作级别。Clang可以使用AST匹配器和回调(与libtooling结合使用)来自动化和扩展此过程。例如,AST匹配器组合

fieldDecl( hasType( tyoedefType().bind("typedef") ) ).bind("field")
将匹配C结构中使用typedef而不是内置类型声明的字段。
bind()
调用使回调可以访问AST节点。下面是一个回调,其
run()
方法获取字段声明的基本类型:

virtual void run(clang::ast_matchers::MatchFinder::MatchResult const & result) override
{
  using namespace clang;
  FieldDecl * f_decl =
      const_cast<FieldDecl *>(result.Nodes.getNodeAs<FieldDecl>("field"));
  TypedefType * tt = const_cast<TypedefType *>(
      result.Nodes.getNodeAs<TypedefType>("typedef"));
  if(f_decl && tt) {
    QualType ut = tt->getDecl()->getUnderlyingType();
    TypedefNameDecl * tnd = tt->getDecl();

    std::string struct_name = f_decl->getParent()->getNameAsString();
    std::string fld_name = f_decl->getNameAsString();
    std::string ut_name = ut.getAsString();
    std::string tnd_name = tnd->getNameAsString();

    std::cout << "Struct '" << struct_name << "' declares field '"
              << fld_name << " with typedef name = '" << tnd_name << "'"
              << ", underlying type = '" << ut_name << "'" << std::endl;
  }
  else {
    // error handling
  }
  return;
}  // run
产生

Struct 'Foo' declares field 'a' with typedef name = 'M_Int', underlying type = 'int'
Struct 'Foo' declares field 'p_f' with typedef name = 'P_Float', underlying type = 'float *'

我在a中提供了一个完整的工作示例应用程序(请参阅apps/typedefinder.cc)。

要查找底层类型,AST是一个很好的工作级别。Clang可以使用AST匹配器和回调(与libtooling结合使用)来自动化和扩展此过程。例如,AST匹配器组合

fieldDecl( hasType( tyoedefType().bind("typedef") ) ).bind("field")
将匹配C结构中使用typedef而不是内置类型声明的字段。
bind()
调用使回调可以访问AST节点。下面是一个回调,其
run()
方法获取字段声明的基本类型:

virtual void run(clang::ast_matchers::MatchFinder::MatchResult const & result) override
{
  using namespace clang;
  FieldDecl * f_decl =
      const_cast<FieldDecl *>(result.Nodes.getNodeAs<FieldDecl>("field"));
  TypedefType * tt = const_cast<TypedefType *>(
      result.Nodes.getNodeAs<TypedefType>("typedef"));
  if(f_decl && tt) {
    QualType ut = tt->getDecl()->getUnderlyingType();
    TypedefNameDecl * tnd = tt->getDecl();

    std::string struct_name = f_decl->getParent()->getNameAsString();
    std::string fld_name = f_decl->getNameAsString();
    std::string ut_name = ut.getAsString();
    std::string tnd_name = tnd->getNameAsString();

    std::cout << "Struct '" << struct_name << "' declares field '"
              << fld_name << " with typedef name = '" << tnd_name << "'"
              << ", underlying type = '" << ut_name << "'" << std::endl;
  }
  else {
    // error handling
  }
  return;
}  // run
产生

Struct 'Foo' declares field 'a' with typedef name = 'M_Int', underlying type = 'int'
Struct 'Foo' declares field 'p_f' with typedef name = 'P_Float', underlying type = 'float *'
我将一个完整的工作示例应用程序放在一个文件夹中(请参阅apps/typedefinder.cc)