use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_target::spec::{HasTargetSpec, Target};
use std::borrow::Cow;
+use std::ffi::CStr;
use std::ops::{Deref, Range};
use std::ptr;
use std::iter::TrustedLen;
}
}
-// This is a really awful way to get a zero-length c-string, but better (and a
-// lot more efficient) than doing str::as_c_str("", ...) every time.
-fn noname() -> *const c_char {
- static CNULL: c_char = 0;
- &CNULL
-}
+// FIXME(eddyb) use a checked constructor when they become `const fn`.
+const EMPTY_C_STR: &CStr = unsafe {
+ CStr::from_bytes_with_nul_unchecked(b"\0")
+};
+
+/// Empty string, to be used where LLVM expects an instruction name, indicating
+/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
+// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
+const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr();
impl BackendTypes for Builder<'_, 'll, 'tcx> {
type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
}
impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
+ fn tcx(&self) -> TyCtxt<'tcx, 'tcx> {
self.cx.tcx
}
}
type CodegenCx = CodegenCx<'ll, 'tcx>;
}
+macro_rules! builder_methods_for_value_instructions {
+ ($($name:ident($($arg:ident),*) => $llvm_capi:ident),+ $(,)?) => {
+ $(fn $name(&mut self, $($arg: &'ll Value),*) -> &'ll Value {
+ unsafe {
+ llvm::$llvm_capi(self.llbuilder, $($arg,)* UNNAMED)
+ }
+ })*
+ }
+}
+
impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn new_block<'b>(
cx: &'a CodegenCx<'ll, 'tcx>,
then,
catch,
bundle,
- noname())
+ UNNAMED)
}
}
}
}
- /* Arithmetic */
- fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
- }
+ builder_methods_for_value_instructions! {
+ add(a, b) => LLVMBuildAdd,
+ fadd(a, b) => LLVMBuildFAdd,
+ sub(a, b) => LLVMBuildSub,
+ fsub(a, b) => LLVMBuildFSub,
+ mul(a, b) => LLVMBuildMul,
+ fmul(a, b) => LLVMBuildFMul,
+ udiv(a, b) => LLVMBuildUDiv,
+ exactudiv(a, b) => LLVMBuildExactUDiv,
+ sdiv(a, b) => LLVMBuildSDiv,
+ exactsdiv(a, b) => LLVMBuildExactSDiv,
+ fdiv(a, b) => LLVMBuildFDiv,
+ urem(a, b) => LLVMBuildURem,
+ srem(a, b) => LLVMBuildSRem,
+ frem(a, b) => LLVMBuildFRem,
+ shl(a, b) => LLVMBuildShl,
+ lshr(a, b) => LLVMBuildLShr,
+ ashr(a, b) => LLVMBuildAShr,
+ and(a, b) => LLVMBuildAnd,
+ or(a, b) => LLVMBuildOr,
+ xor(a, b) => LLVMBuildXor,
+ neg(x) => LLVMBuildNeg,
+ fneg(x) => LLVMBuildFNeg,
+ not(x) => LLVMBuildNot,
+ unchecked_sadd(x, y) => LLVMBuildNSWAdd,
+ unchecked_uadd(x, y) => LLVMBuildNUWAdd,
+ unchecked_ssub(x, y) => LLVMBuildNSWSub,
+ unchecked_usub(x, y) => LLVMBuildNUWSub,
+ unchecked_smul(x, y) => LLVMBuildNSWMul,
+ unchecked_umul(x, y) => LLVMBuildNUWMul,
}
fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
- fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
- }
- }
-
fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
- fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
- }
- }
-
fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
-
- fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
- fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
- }
- }
-
fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
- fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn neg(&mut self, v: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildNeg(self.llbuilder, v, noname())
- }
- }
-
- fn fneg(&mut self, v: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
- }
- }
-
- fn not(&mut self, v: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildNot(self.llbuilder, v, noname())
- }
- }
-
fn checked_binop(
&mut self,
oop: OverflowOp,
fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
unsafe {
let alloca = if name.is_empty() {
- llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
+ llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED)
} else {
let name = SmallCStr::new(name);
llvm::LLVMBuildAlloca(self.llbuilder, ty,
align: Align) -> &'ll Value {
unsafe {
let alloca = if name.is_empty() {
- llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname())
+ llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED)
} else {
let name = SmallCStr::new(name);
llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len,
fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
unsafe {
- let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
+ let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
load
}
fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
unsafe {
- let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
+ let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
llvm::LLVMSetVolatile(load, llvm::True);
load
}
let load = llvm::LLVMRustBuildAtomicLoad(
self.llbuilder,
ptr,
- noname(),
+ UNNAMED,
AtomicOrdering::from_generic(order),
);
// LLVM requires the alignment of atomic loads to be at least the size of the type.
fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
unsafe {
llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
- indices.len() as c_uint, noname())
+ indices.len() as c_uint, UNNAMED)
}
}
fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
unsafe {
llvm::LLVMBuildInBoundsGEP(
- self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
+ self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, UNNAMED)
}
}
fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
assert_eq!(idx as c_uint as u64, idx);
unsafe {
- llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
+ llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, UNNAMED)
}
}
/* Casts */
fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
+ llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,UNNAMED)
}
}
fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
let op = llvm::IntPredicate::from_generic(op);
unsafe {
- llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
+ llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED)
}
}
fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
+ llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED)
}
}
else_val: &'ll Value,
) -> &'ll Value {
unsafe {
- llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
+ llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, UNNAMED)
}
}
#[allow(dead_code)]
fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
+ llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED)
}
}
fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
unsafe {
- llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
+ llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, UNNAMED)
}
}
fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
assert_eq!(idx as c_uint as u64, idx);
unsafe {
- llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
+ llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, UNNAMED)
}
}
assert_eq!(idx as c_uint as u64, idx);
unsafe {
llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
- noname())
+ UNNAMED)
}
}
num_clauses: usize) -> &'ll Value {
unsafe {
llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
- num_clauses as c_uint, noname())
+ num_clauses as c_uint, UNNAMED)
}
}
llfn,
args.as_ptr() as *const &llvm::Value,
args.len() as c_uint,
- bundle, noname()
+ bundle, UNNAMED
)
}
}
fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED)
}
}
}
}
-impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
-fn get_static(&mut self, def_id: DefId) -> &'ll Value {
+impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> {
+ fn get_static(&mut self, def_id: DefId) -> &'ll Value {
// Forward to the `get_static` method of `CodegenCx`
self.cx().get_static(def_id)
}
idx: &'ll Value,
) -> &'ll Value {
unsafe {
- llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
+ llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, UNNAMED)
}
}
mask: &'ll Value,
) -> &'ll Value {
unsafe {
- llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
+ llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, UNNAMED)
}
}
ret.expect("LLVM does not have support for catchret")
}
- fn check_store<'b>(&mut self,
- val: &'ll Value,
- ptr: &'ll Value) -> &'ll Value {
+ fn check_store(&mut self, val: &'ll Value, ptr: &'ll Value) -> &'ll Value {
let dest_ptr_ty = self.cx.val_ty(ptr);
let stored_ty = self.cx.val_ty(val);
let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
+ llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED)
}
}
fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
assert_eq!(vals.len(), bbs.len());
let phi = unsafe {
- llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
+ llvm::LLVMBuildPhi(self.llbuilder, ty, UNNAMED)
};
unsafe {
llvm::LLVMAddIncoming(phi, vals.as_ptr(),