/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildAtomicRMWUmin(unsigned OldValRes, unsigned Addr,
unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert \p Res = G_BLOCK_ADDR \p BA
+ ///
+ /// G_BLOCK_ADDR computes the address of a basic block.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res must be a generic virtual register of a pointer type.
+ ///
+ /// \return The newly created instruction.
+ MachineInstrBuilder buildBlockAddress(unsigned Res, const BlockAddress *BA);
};
/// A CRTP class that contains methods for building instructions that can
/// Generic AddressSpaceCast.
HANDLE_TARGET_OPCODE(G_ADDRSPACE_CAST)
+/// Generic block address
+HANDLE_TARGET_OPCODE(G_BLOCK_ADDR)
+
// TODO: Add more generic opcodes as we move along.
/// Marker for the end of the generic opcode.
/// This is used to check if an opcode is in the range of the
/// generic opcodes.
-HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_ADDRSPACE_CAST)
+HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BLOCK_ADDR)
/// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific post-isel opcode values start here.
let InOperandList = (ins type1:$src);
let hasSideEffects = 0;
}
+
+def G_BLOCK_ADDR : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins unknown:$ba);
+ let hasSideEffects = 0;
+}
+
//------------------------------------------------------------------------------
// Binary ops.
//------------------------------------------------------------------------------
Ops.push_back(getOrCreateVReg(*CV->getOperand(i)));
}
EntryBuilder.buildMerge(Reg, Ops);
+ } else if (auto *BA = dyn_cast<BlockAddress>(&C)) {
+ EntryBuilder.buildBlockAddress(Reg, BA);
} else
return false;
MMO);
}
+MachineInstrBuilder
+MachineIRBuilderBase::buildBlockAddress(unsigned Res, const BlockAddress *BA) {
+#ifndef NDEBUG
+ assert(getMRI()->getType(Res).isPointer() && "invalid res type");
+#endif
+
+ return buildInstr(TargetOpcode::G_BLOCK_ADDR).addDef(Res).addBlockAddress(BA);
+}
+
void MachineIRBuilderBase::validateTruncExt(unsigned Dst, unsigned Src,
bool IsExtend) {
#ifndef NDEBUG
%oldval.trunc = trunc i256 %oldval to i32
ret i32 %oldval.trunc
}
+
+@addr = global i8* null
+
+define void @test_blockaddress() {
+; CHECK-LABEL: name: test_blockaddress
+; CHECK: [[BADDR:%[0-9]+]]:_(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)
+; CHECK: G_STORE [[BADDR]](p0)
+ store i8* blockaddress(@test_blockaddress, %block), i8** @addr
+ indirectbr i8* blockaddress(@test_blockaddress, %block), [label %block]
+block:
+ ret void
+}