简体   繁体   中英

[3.0]Question about how to use the store IR instruction to obtain the blockaddress

I am writing to enquire about a question. When I read the IR language generated by a piece of C programs, I found that in C programs, the behavior of getting tag addresses is handled by a store directive after it is translated into IR.

store i8* blockaddress(@func_name, %label_name), i8** %val_name

However, I read the official documents. Here's how Blockaddress works:

blockaddress(@function, %block) The 'blockaddress' constant computes the address of the specified basic block in the specified function, and always has an i8* type. Taking the address of the entry block is illegal. This value only has defined behavior when used as an operand to the '[indirectbr](file:///D:/opensourse/llvm-3.0.src/docs/LangRef.html#i_indirectbr)' instruction, or for comparisons against null. Pointer equality tests between labels addresses results in undefined behavior — though, again, comparison against null is ok, and no label is equal to the null pointer. This may be passed around as an opaque pointer sized value as long as the bits are not inspected. This allows ptrtoint and arithmetic to be performed on these values so long as the original value is reconstituted before the indirectbr instruction. Finally, some targets may provide defined semantics when using the value as the operand to an inline assembly, but that is target specific.

So I want to figure out how stores construct blockaddress in the IR program by storing them in%5. What should I do if I want to use C++ to construct this store directive to get Addresses of Basic Blocks?

I made some attempts, such as constructing an indirectbr:

    irBuilder.SetInsertPoint(indirectbr_bb);
    IndirectBrInst *indirect_br = IndirectBrInst::Create(BlockAddress::get(func, instr2_bb), 0, indirectbr_bb);
    indirect_br->addDestination(instr1_bb);
    indirect_br->addDestination(instr2_bb);

The IR program generated is as follows:

indirectbr_bb:                                    ; preds = %dispatch_then_bb
  indirectbr i8* blockaddress(@jit_func, %instr2_bb), [label %instr1_bb, label %instr2_bb]

After my test, it can be executed correctly. Therefore, I want to know how to construct a similar store IR to store the address of the basic block in the array.

Blockaddress::get(basicblock *bb) returns a blockaddress pointer, which is a subclass of constant and a derived class of Value. In LLVM IR, all variables are of type Value. So we can do this:

ArrayType *arrayType = ArrayType::get(irBuilder.getInt8PtrTy(), 1024);
module->getOrInsertGlobal("label_array", arrayType);
GlobalVariable *label_array = module->getNamedGlobal("label_array");

vector <Constant *> array_elems;
array_elems.push_back(BlockAddress::get(func, ret_bb));
array_elems.push_back(BlockAddress::get(func, instr1_bb));
array_elems.push_back(BlockAddress::get(func, instr2_bb));
label_array->setInitializer(ConstantArray::get(arrayType, array_elems));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM