Skip to content

Commit 7943f9e

Browse files
committed
experiment
1 parent 7e54ed2 commit 7943f9e

File tree

3 files changed

+63
-84
lines changed

3 files changed

+63
-84
lines changed

crates/rustc_codegen_spirv/src/abi.rs

+59-75
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rspirv::spirv::{StorageClass, Word};
88
use rustc_data_structures::fx::FxHashMap;
99
use rustc_errors::ErrorGuaranteed;
1010
use rustc_index::Idx;
11-
use rustc_middle::query::Providers;
11+
use rustc_middle::query::{Key, Providers};
1212
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
1313
use rustc_middle::ty::GenericArgsRef;
1414
use rustc_middle::ty::{
@@ -21,7 +21,7 @@ use rustc_span::DUMMY_SP;
2121
use rustc_span::{Span, Symbol};
2222
use rustc_target::abi::call::{ArgAbi, ArgAttributes, FnAbi, PassMode};
2323
use rustc_target::abi::{
24-
Abi, Align, FieldsShape, LayoutS, Primitive, Scalar, Size, TagEncoding, VariantIdx, Variants,
24+
Abi, Align, FieldsShape, LayoutS, Primitive, Scalar, Size, VariantIdx, Variants,
2525
};
2626
use rustc_target::spec::abi::Abi as SpecAbi;
2727
use std::cell::RefCell;
@@ -94,86 +94,66 @@ pub(crate) fn provide(providers: &mut Providers) {
9494
Ok(readjust_fn_abi(tcx, result?))
9595
};
9696

97-
// FIXME(eddyb) remove this by deriving `Clone` for `LayoutS` upstream.
98-
// FIXME(eddyb) the `S` suffix is a naming antipattern, rename upstream.
99-
fn clone_layout(layout: &LayoutS) -> LayoutS {
100-
let LayoutS {
101-
ref fields,
102-
ref variants,
103-
abi,
104-
largest_niche,
105-
align,
106-
size,
107-
max_repr_align,
108-
unadjusted_abi_align,
109-
} = *layout;
110-
LayoutS {
111-
fields: match *fields {
112-
FieldsShape::Primitive => FieldsShape::Primitive,
113-
FieldsShape::Union(count) => FieldsShape::Union(count),
114-
FieldsShape::Array { stride, count } => FieldsShape::Array { stride, count },
115-
FieldsShape::Arbitrary {
116-
ref offsets,
117-
ref memory_index,
118-
} => FieldsShape::Arbitrary {
119-
offsets: offsets.clone(),
120-
memory_index: memory_index.clone(),
121-
},
122-
},
123-
variants: match *variants {
124-
Variants::Single { index } => Variants::Single { index },
125-
Variants::Multiple {
126-
tag,
127-
ref tag_encoding,
128-
tag_field,
129-
ref variants,
130-
} => Variants::Multiple {
131-
tag,
132-
tag_encoding: match *tag_encoding {
133-
TagEncoding::Direct => TagEncoding::Direct,
134-
TagEncoding::Niche {
135-
untagged_variant,
136-
ref niche_variants,
137-
niche_start,
138-
} => TagEncoding::Niche {
139-
untagged_variant,
140-
niche_variants: niche_variants.clone(),
141-
niche_start,
142-
},
143-
},
144-
tag_field,
145-
variants: variants.clone(),
146-
},
147-
},
148-
abi,
149-
largest_niche,
150-
align,
151-
size,
152-
max_repr_align,
153-
unadjusted_abi_align,
154-
}
155-
}
15697
providers.layout_of = |tcx, key| {
157-
let TyAndLayout { ty, mut layout } =
158-
(rustc_interface::DEFAULT_QUERY_PROVIDERS.layout_of)(tcx, key)?;
98+
let orig = (rustc_interface::DEFAULT_QUERY_PROVIDERS.layout_of)(tcx, key)?;
15999

160-
#[allow(clippy::match_like_matches_macro)]
161-
let hide_niche = match ty.kind() {
162-
ty::Bool => true,
163-
_ => false,
164-
};
100+
let mut modified: Option<LayoutS> = None;
165101

166-
if hide_niche {
167-
layout = tcx.mk_layout(LayoutS {
168-
largest_niche: None,
169-
..clone_layout(layout.0.0)
170-
});
171-
}
102+
hide_bool_niche(&tcx, orig, &mut modified);
103+
adjust_vector_layout(&tcx, orig, &mut modified);
172104

105+
let ty = orig.ty;
106+
107+
let layout = if let Some(modified) = modified {
108+
tcx.mk_layout(modified)
109+
} else {
110+
orig.layout
111+
};
173112
Ok(TyAndLayout { ty, layout })
174113
};
175114
}
176115

116+
fn hide_bool_niche<'tcx>(_cx: &TyCtxt<'tcx>, orig: TyAndLayout<'tcx>, modified: &mut Option<LayoutS>) {
117+
#[allow(clippy::match_like_matches_macro)]
118+
let hide_niche = match orig.ty.kind() {
119+
ty::Bool => true,
120+
_ => false,
121+
};
122+
123+
if hide_niche {
124+
let layout = modified.get_or_insert_with(|| orig.layout.0.0.clone());
125+
layout.largest_niche = None;
126+
}
127+
}
128+
129+
fn adjust_vector_layout<'tcx>(cx: &TyCtxt<'tcx>, orig: TyAndLayout<'tcx>, modified: &mut Option<LayoutS>) {
130+
// in spirv, in most cases vectors have align equal to their element type. in block resource
131+
// contexts (storage, uniform, etc) the rules are sometimes more restrictive than that, but
132+
// it's best to use the least common denominator here since if a layout get somputed that is
133+
// not valid under the given vulkan environment then spirv-val will catch it and the user
134+
// can manually adjust the block layout, whereas if we use the most restrictive rules then
135+
// everywhere else suffers.
136+
//
137+
// it may be possible for us to figure out whether we're in a block context and what the
138+
// currently enabled restrictions allow and compute this more intelligently, but I'm not sure
139+
// whether that can break rustc assumptions about abi (what if the same type is used in
140+
// multiple places with competing requirements?)
141+
if let Abi::Vector { element, count } = orig.abi {
142+
let layout = modified.get_or_insert_with(|| orig.layout.0.0.clone());
143+
let element_align = element.align(cx).abi;
144+
let element_size = element.size(cx);
145+
let repr_align_align = orig.ty.ty_adt_id()
146+
.and_then(|did| cx.repr_options_of_def(did).align);
147+
if let Some(align) = repr_align_align {
148+
layout.align.abi = align.max(element_align);
149+
} else {
150+
layout.align.abi = element_align;
151+
}
152+
layout.align.pref = layout.align.abi;
153+
layout.size = (element_size * count).align_to(layout.align.abi);
154+
}
155+
}
156+
177157
/// If a struct contains a pointer to itself, even indirectly, then doing a naiive recursive walk
178158
/// of the fields will result in an infinite loop. Because pointers are the only thing that are
179159
/// allowed to be recursive, keep track of what pointers we've translated, or are currently in the
@@ -634,7 +614,8 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>
634614
}
635615
}
636616
FieldsShape::Array { stride, count } => {
637-
let element_type = ty.field(cx, 0).spirv_type(span, cx);
617+
let element_type_hl = ty.field(cx, 0);
618+
let element_type = element_type_hl.spirv_type(span, cx);
638619
if ty.is_unsized() {
639620
// There's a potential for this array to be sized, but the element to be unsized, e.g. `[[u8]; 5]`.
640621
// However, I think rust disallows all these cases, so assert this here.
@@ -653,6 +634,9 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>
653634
.sizeof(cx)
654635
.expect("Unexpected unsized type in sized FieldsShape::Array")
655636
.align_to(element_spv.alignof(cx));
637+
if stride_spv != stride {
638+
eprintln!("element type: {:?}\nelement spv type: {:?}", &element_type_hl, &element_spv);
639+
}
656640
assert_eq!(stride_spv, stride);
657641
SpirvType::Array {
658642
element: element_type,

crates/rustc_codegen_spirv/src/spirv_type.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ impl SpirvType<'_> {
331331
Self::Integer(width, _) | Self::Float(width) => Size::from_bits(width),
332332
Self::Adt { size, .. } => size?,
333333
Self::Vector { element, count } => {
334-
cx.lookup_type(element).sizeof(cx)? * count.next_power_of_two() as u64
334+
cx.lookup_type(element).sizeof(cx)? * count as u64
335335
}
336336
Self::Matrix { element, count } => cx.lookup_type(element).sizeof(cx)? * count as u64,
337337
Self::Array { element, count } => {
@@ -357,14 +357,8 @@ impl SpirvType<'_> {
357357
Self::Bool => Align::from_bytes(1).unwrap(),
358358
Self::Integer(width, _) | Self::Float(width) => Align::from_bits(width as u64).unwrap(),
359359
Self::Adt { align, .. } => align,
360-
// Vectors have size==align
361-
Self::Vector { .. } => Align::from_bytes(
362-
self.sizeof(cx)
363-
.expect("alignof: Vectors must be sized")
364-
.bytes(),
365-
)
366-
.expect("alignof: Vectors must have power-of-2 size"),
367-
Self::Array { element, .. }
360+
Self::Vector { element, .. }
361+
| Self::Array { element, .. }
368362
| Self::RuntimeArray { element }
369363
| Self::Matrix { element, .. } => cx.lookup_type(element).alignof(cx),
370364
Self::Pointer { .. } => cx.tcx.data_layout.pointer_align.abi,

crates/rustc_codegen_spirv/src/target.rs

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ impl SpirvTarget {
9898
Target {
9999
llvm_target: self.to_string().into(),
100100
pointer_width: 32,
101+
// note: vector size and align gets patched in abi.rs too
101102
data_layout: "e-m:e-p:32:32:32-i64:64-n8:16:32:64".into(),
102103
arch: ARCH.into(),
103104
options: self.init_target_opts(),

0 commit comments

Comments
 (0)