-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make librustc_codegen_llvm
aware of LLVM address spaces.
#51576
Make librustc_codegen_llvm
aware of LLVM address spaces.
#51576
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rustbuild changes look acceptable to me.
src/bootstrap/native.rs
Outdated
@@ -38,6 +38,7 @@ use cache::Interned; | |||
pub struct Llvm { | |||
pub target: Interned<String>, | |||
pub emscripten: bool, | |||
pub dump_enabled: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no need for this here as AFAICT it's always globally set, we never do anything but pass it in from config.llvm_dump_enabled.
src/librustc_codegen_llvm/builder.rs
Outdated
@@ -15,7 +15,7 @@ use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect}; | |||
use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef}; | |||
use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef}; | |||
use common::*; | |||
use type_::Type; | |||
use type_::{Type, }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed!
src/librustc_target/Cargo.toml
Outdated
@@ -10,6 +10,7 @@ crate-type = ["dylib"] | |||
|
|||
[dependencies] | |||
bitflags = "1.0" | |||
syntax_pos = { path = "../libsyntax_pos" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see this dependency actually being used -- but maybe I'm missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rustc_target
shouldn't have any dependencies on the compiler, so hopefully this is unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used for custom address space names.
Oh, it was. I forgot I had removed it.
r? @eddyb probably |
src/librustc_errors/lib.rs
Outdated
@@ -553,6 +553,13 @@ impl Handler { | |||
db.emit(); | |||
panic!(ExplicitBug); | |||
} | |||
pub fn bug_no_panic(&self, msg: &str) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
src/librustc_codegen_llvm/Cargo.toml
Outdated
@@ -47,3 +47,4 @@ jemalloc = ["rustc_target/jemalloc"] | |||
# when this option is enabled or not. That way we can build two, cache two | |||
# artifacts, and have nice speedy rebuilds. | |||
emscripten = ["rustc_llvm/emscripten"] | |||
dump = ["rustc_llvm/dump"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing newline at the end of file.
src/librustc_codegen_llvm/abi.rs
Outdated
bx.pointercast(dst.llval, Type::i8p(cx)), | ||
bx.pointercast(llscratch, Type::i8p(cx)), | ||
bx.pointercast(dst.llval, ti8.ptr_to_as(dst_addr_space)), | ||
bx.pointercast(llscratch, ti8.ptr_to_as(addr_space)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is common, wouldn't a replacement for pointercast
that only casts the pointee, but preserves the AS, be better?
src/librustc_codegen_llvm/abi.rs
Outdated
@@ -567,7 +571,9 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { | |||
} | |||
PassMode::Cast(cast) => cast.llvm_type(cx), | |||
PassMode::Indirect(_) => { | |||
llargument_tys.push(self.ret.memory_ty(cx).ptr_to()); | |||
let ty = self.ret.memory_ty(cx) | |||
.ptr_to_as(cx.alloca_addr_space()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having a method to retrieve a specific AS and then another to create a pointer type, why not have e.g. .alloca_ptr_to(cx)
or .ptr_to(cx, AddrSpaceKind::Alloca)
(okay, the latter is a bit long).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually already have those functions, I just probably added them after I wrote some of this 😄
src/librustc_codegen_llvm/abi.rs
Outdated
llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1)); | ||
let data_ty = arg.layout.scalar_pair_element_llvm_type(cx, 0) | ||
.as_flat_addr_space(cx); | ||
// Keep the original addrspace, dst's of course aren't ptrs, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By "dst" you mean "slice (length)"? Also, I should note this doesn't necessarily work.
The pair could just as well be (&T, &U)
where T: Sized, U: Sized
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better approach might be to pass something extra to scalar_pair_element_llvm_type
. Same for everything else, really.
src/librustc_codegen_llvm/base.rs
Outdated
(bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None)) | ||
} | ||
(&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => { | ||
let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty()); | ||
assert!(bx.cx.type_is_sized(a)); | ||
let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to(); | ||
let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx) | ||
.ptr_to_as(val_ty(src).address_space()); | ||
(bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, regarding the usecase of only needed to cast the pointee type.
src/librustc_codegen_llvm/builder.rs
Outdated
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/librustc_codegen_llvm/common.rs
Outdated
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{ | ||
bug!("symbol `{}` is already defined", sym); | ||
}); | ||
let addr_space = cx.default_const_addr_space(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe pass the AddrSpaceKind
enum value around instead of the LLVM AS number?
src/librustc_codegen_llvm/consts.rs
Outdated
@@ -64,13 +64,16 @@ fn set_global_alignment(cx: &CodegenCx, | |||
pub fn addr_of_mut(cx: &CodegenCx, | |||
cv: ValueRef, | |||
align: Align, | |||
kind: &str) | |||
kind: &str, | |||
addr_space: Option<AddrSpaceIdx>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There shouldn't be that many calls, making this non-optional (and using AddrSpaceKind
) would be better IMO.
src/librustc_codegen_llvm/context.rs
Outdated
pub alloca_i8p_ty: Type, | ||
pub const_i8p_ty: Type, | ||
pub global_i8p_ty: Type, | ||
pub flat_i8p_ty: Type, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably shouldn't have cached types like these.
src/librustc_codegen_llvm/context.rs
Outdated
pub dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>, | ||
|
||
eh_personality: Cell<Option<ValueRef>>, | ||
eh_unwind_resume: Cell<Option<ValueRef>>, | ||
pub rust_try_fn: Cell<Option<ValueRef>>, | ||
|
||
intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>, | ||
intrinsics: RefCell<FxHashMap<Cow<'static, str>, ValueRef>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is worse, because it incurs extra branching. Might as well switch it to String
.
src/librustc_codegen_llvm/context.rs
Outdated
ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void); | ||
ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void); | ||
if key.starts_with("llvm.memcpy.") || key.starts_with("llvm.memmove") || | ||
key.starts_with("llvm.memset") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
memcpy has a dot at the end, but the others don't?
llpair = bx.insert_value(llpair, a, 0); | ||
let b = b.copy_addr_space(bx, val_ty(llpair).struct_element_type(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would these two be needed?
PlaceRef { | ||
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. | ||
llval: bx.pointercast(llval, field.llvm_type(cx).ptr_to()), | ||
llval: bx.pointercast(llval, dest_ty), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, could have a pointercast
variant that only casts the pointee.
let asp = val_ty(downcast.llval).address_space(); | ||
downcast.llval = bx | ||
.pointercast(downcast.llval, | ||
variant_ty.ptr_to_as(asp)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
@@ -17,6 +17,7 @@ use rustc::middle::lang_items::ExchangeMallocFnLangItem; | |||
use rustc_apfloat::{ieee, Float, Status, Round}; | |||
use std::{u128, i128}; | |||
|
|||
use abi::{FnType, FnTypeExt, }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Superfluous ,
.
} else { | ||
fn_ret_val | ||
}; | ||
let val = bx.pointercast(ret_val, llty_ptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this all doing? Why would the function being called here ever return by indirection?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accidentally included. Was created when I was trying to figure out how to work with the AMDGPU target machine. I tried having every function be the amdgpu kernel abi, which doesn't allow non-void
return types.
Removed in the next version, to be pushed Soon(TM).
} else { | ||
cx.default_global_addr_space() | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should avoid touching the HIR here, but it's not clear what requirements there actually are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need the address space of the global for the global's LLVM type, meaning it needs to compute the same address space as consts::codegen_static
.
At the time, I wasn't aware of a better way, but the next version now does what MonoItemExt::define
does.
src/librustc_codegen_llvm/type_.rs
Outdated
pub fn is_array(&self) -> bool { self.kind() == llvm::TypeKind::Array } | ||
pub fn is_vector(&self) -> bool { self.kind() == llvm::TypeKind::Vector } | ||
pub fn is_struct(&self) -> bool { self.kind() == llvm::TypeKind::Struct } | ||
pub fn is_func(&self) -> bool { self.kind() == llvm::TypeKind::Function } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why all of these? We should avoid introspecting LLVM types at all costs IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how any of the code around read-only and read-write global address spaces, actually works. Why are vtable pointers different from any other pointer?
If there is a flat address space, why isn't it used more often? Some documentation would help.
I hope there is a simpler way to support the target platform you want.
3ad92f6
to
2ee942f
Compare
This PR was labelled as Blocked 2 months ago:
@BatmanAoD is it still the case? |
Review ping @eddyb |
☔ The latest upstream changes (presumably #55982) made this pull request unmergeable. Please resolve the merge conflicts. |
2ee942f
to
e517b7c
Compare
src/librustc_codegen_llvm/context.rs
Outdated
.unwrap_or_default(); | ||
let instruction_addr_space = | ||
tcx.sess.target.target.options.addr_spaces | ||
.get(&AddrSpaceKind::Flat) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be Instruction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thanks
src/librustc_target/spec/mod.rs
Outdated
let kinds = vec![AddrSpaceKind::ReadOnly, | ||
AddrSpaceKind::ReadWrite, | ||
AddrSpaceKind::Alloca, | ||
AddrSpaceKind::Flat, ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Instruction
?
b719335
to
7a13695
Compare
☔ The latest upstream changes (presumably #57108) made this pull request unmergeable. Please resolve the merge conflicts. |
286b70a
to
f0abb1b
Compare
☔ The latest upstream changes (presumably #57145) made this pull request unmergeable. Please resolve the merge conflicts. |
f0abb1b
to
724ab44
Compare
☔ The latest upstream changes (presumably #57416) made this pull request unmergeable. Please resolve the merge conflicts. |
In order to not require overloading functions based on their argument's address space (among other things), we require the presence of a "flat" (ie an address space which is shared with every other address space) address space. This isn't exposed in any way to Rust code. This just makes Rust compatible with LLVM target machines which, for example, place allocas in a different address space. `amdgcn-amd-amdhsa-amdgiz` is a specific example, which places allocas in address space 5 or the private (at the work item level) address space.
…l address space where possible.
724ab44
to
1019e20
Compare
☔ The latest upstream changes (presumably #58316) made this pull request unmergeable. Please resolve the merge conflicts. |
ping from triage @DiamondLovesYou you have conflicts you need to resolve |
ping from triage @DiamondLovesYou |
In order to not require overloading functions based on their argument's address
space (among other things), we require the presence of a "flat" (ie an address
space which is shared with every other address space) address space.
This isn't exposed in any way to Rust code. This just makes Rust compatible with
LLVM target machines which, for example, place allocas in a different address
space.
amdgcn-amd-amdhsa-amdgiz
is a specific example, which places allocas inaddress space 5 or the private (at the work item level) address space. This
includes working with nonuniform sized pointers.