Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLVM. How to access to struct fields based on their names?

I have little example code in C++:

struct RecordTest
{
    int value1;
    int value2;
};

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

and LLVM 3.4 IR for it:

%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
}

and a pretty easy question: How can I access to RecordTest fields (when I parsing .cpp), without their indexes, with only names (value1 and value2)?

I know only one way (from llc -march=cpp) - with indexes:

  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);

So, can I translate from C++ to LLVM IR, if I don't know the indexes of the fields (const_int32_5 and const_int32_6 in code above) ?

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

So, we can't access to field names. And if we need it (and we do, if we parse .cpp), we can write something like this:

 // 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;
        }
    }

Is this right ?

like image 495
kpdev Avatar asked Jul 01 '13 16:07

kpdev


1 Answers

You cannot access the fields of the struct by name, only by index. This information is just normally not there when you compile with Clang.

There is one exception to this, and this is if you compiled with debug information. In that case, you'll have ample data about the type; specifically, you'll get the order of the fields, along with a metadata entry for each field which contains its name (and other useful stuff, such as its offset from the beginning of the type).

Read more about this on the Source Level Debugging guide - and particularly, see this section about struct encoding, with its very nice example.

Take a look at DebugInfo.h for classes to help on querying debug info, though I think you're going to have to do some manually digging anyway.

like image 151
Oak Avatar answered Nov 10 '22 10:11

Oak