Add callbr support to LLVM wrapper
This commit is contained in:
parent
3b1dd1bfa9
commit
27e6ee102e
@ -1547,6 +1547,58 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn callbr(
|
||||
&mut self,
|
||||
llty: &'ll Type,
|
||||
fn_attrs: Option<&CodegenFnAttrs>,
|
||||
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
|
||||
llfn: &'ll Value,
|
||||
args: &[&'ll Value],
|
||||
default_dest: &'ll BasicBlock,
|
||||
indirect_dest: &[&'ll BasicBlock],
|
||||
funclet: Option<&Funclet<'ll>>,
|
||||
) -> &'ll Value {
|
||||
debug!("invoke {:?} with args ({:?})", llfn, args);
|
||||
|
||||
let args = self.check_call("callbr", llty, llfn, args);
|
||||
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
|
||||
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
|
||||
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
|
||||
if let Some(funclet_bundle) = funclet_bundle {
|
||||
bundles.push(funclet_bundle);
|
||||
}
|
||||
|
||||
// Emit CFI pointer type membership test
|
||||
self.cfi_type_test(fn_attrs, fn_abi, llfn);
|
||||
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
|
||||
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
let callbr = unsafe {
|
||||
llvm::LLVMRustBuildCallBr(
|
||||
self.llbuilder,
|
||||
llty,
|
||||
llfn,
|
||||
default_dest,
|
||||
indirect_dest.as_ptr(),
|
||||
indirect_dest.len() as c_uint,
|
||||
args.as_ptr(),
|
||||
args.len() as c_uint,
|
||||
bundles.as_ptr(),
|
||||
bundles.len() as c_uint,
|
||||
UNNAMED,
|
||||
)
|
||||
};
|
||||
if let Some(fn_abi) = fn_abi {
|
||||
fn_abi.apply_attrs_callsite(self, callbr);
|
||||
}
|
||||
callbr
|
||||
}
|
||||
|
||||
// Emits CFI pointer type membership tests.
|
||||
fn cfi_type_test(
|
||||
&mut self,
|
||||
|
@ -1617,6 +1617,20 @@ extern "C" {
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
|
||||
pub fn LLVMRustBuildCallBr<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Fn: &'a Value,
|
||||
DefaultDest: &'a BasicBlock,
|
||||
IndirectDests: *const &'a BasicBlock,
|
||||
NumIndirectDests: c_uint,
|
||||
Args: *const &'a Value,
|
||||
NumArgs: c_uint,
|
||||
OpBundles: *const &OperandBundleDef<'a>,
|
||||
NumOpBundles: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
|
||||
pub fn LLVMRustSetFastMath(Instr: &Value);
|
||||
pub fn LLVMRustSetAlgebraicMath(Instr: &Value);
|
||||
pub fn LLVMRustSetAllowReassoc(Instr: &Value);
|
||||
|
@ -1539,6 +1539,31 @@ LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||
Name));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||
LLVMBasicBlockRef DefaultDest,
|
||||
LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests,
|
||||
LLVMValueRef *Args, unsigned NumArgs,
|
||||
OperandBundleDef **OpBundles, unsigned NumOpBundles,
|
||||
const char *Name) {
|
||||
Value *Callee = unwrap(Fn);
|
||||
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
||||
|
||||
// FIXME: Is there a way around this?
|
||||
std::vector<BasicBlock*> IndirectDestsUnwrapped;
|
||||
IndirectDestsUnwrapped.reserve(NumIndirectDests);
|
||||
for (unsigned i = 0; i < NumIndirectDests; ++i) {
|
||||
IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i]));
|
||||
}
|
||||
|
||||
return wrap(unwrap(B)->CreateCallBr(
|
||||
FTy, Callee, unwrap(DefaultDest),
|
||||
ArrayRef<BasicBlock*>(IndirectDestsUnwrapped),
|
||||
ArrayRef<Value*>(unwrap(Args), NumArgs),
|
||||
ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles),
|
||||
Name));
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
|
||||
LLVMBasicBlockRef BB) {
|
||||
auto Point = unwrap(BB)->getFirstInsertionPt();
|
||||
|
Loading…
x
Reference in New Issue
Block a user