mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
Emit OpSource
for every source file referenced via OpLine
.
This commit is contained in:
parent
b560a21453
commit
3fb4f9176a
@ -657,11 +657,12 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
fn set_span(&mut self, span: Span) {
|
||||
self.current_span = Some(span);
|
||||
let loc = self.cx.tcx.sess.source_map().lookup_char_pos(span.lo());
|
||||
let file = self
|
||||
.builder
|
||||
.def_string(format!("{}", loc.file.name.prefer_remapped()));
|
||||
self.emit()
|
||||
.line(file, loc.line as u32, loc.col_display as u32);
|
||||
let file = self.builder.def_debug_file(loc.file);
|
||||
self.emit().line(
|
||||
file.file_name_op_string_id,
|
||||
loc.line as u32,
|
||||
loc.col_display as u32,
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME(eddyb) change `Self::Function` to be more like a function index.
|
||||
|
@ -5,14 +5,20 @@ use crate::symbols::Symbols;
|
||||
use crate::target::SpirvTarget;
|
||||
use crate::target_feature::TargetFeature;
|
||||
use rspirv::dr::{Block, Builder, Module, Operand};
|
||||
use rspirv::spirv::{AddressingModel, Capability, MemoryModel, Op, StorageClass, Word};
|
||||
use rspirv::spirv::{
|
||||
AddressingModel, Capability, MemoryModel, Op, SourceLanguage, StorageClass, Word,
|
||||
};
|
||||
use rspirv::{binary::Assemble, binary::Disassemble};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_middle::bug;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::{SourceFile, Span, DUMMY_SP};
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter;
|
||||
use std::{fs::File, io::Write, path::Path};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||
@ -321,6 +327,42 @@ struct WithConstLegality<V> {
|
||||
legal: Result<(), IllegalConst>,
|
||||
}
|
||||
|
||||
/// `HashMap` key type (for `debug_file_cache` in `BuilderSpirv`), which is
|
||||
/// equivalent to a whole `rustc` `SourceFile`, but has O(1) `Eq` and `Hash`
|
||||
/// implementations (i.e. not involving the path or the contents of the file).
|
||||
///
|
||||
/// This is possible because we can compare `Lrc<SourceFile>`s by equality, as
|
||||
/// `rustc`'s `SourceMap` already ensures that only one `SourceFile` will be
|
||||
/// allocated for some given file. For hashing, we could hash the address, or
|
||||
///
|
||||
struct DebugFileKey(Lrc<SourceFile>);
|
||||
|
||||
impl PartialEq for DebugFileKey {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let (Self(self_sf), Self(other_sf)) = (self, other);
|
||||
Lrc::ptr_eq(self_sf, other_sf)
|
||||
}
|
||||
}
|
||||
impl Eq for DebugFileKey {}
|
||||
|
||||
impl Hash for DebugFileKey {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let Self(sf) = self;
|
||||
sf.name_hash.hash(state);
|
||||
sf.src_hash.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct DebugFileSpirv {
|
||||
/// The SPIR-V ID for the result of the `OpString` instruction containing
|
||||
/// the file name - this is what e.g. `OpLine` uses to identify the file.
|
||||
///
|
||||
/// All other details about the file are also attached to this ID, using
|
||||
/// other instructions that don't produce their own IDs (e.g. `OpSource`).
|
||||
pub file_name_op_string_id: Word,
|
||||
}
|
||||
|
||||
/// Cursor system:
|
||||
///
|
||||
/// The LLVM module builder model (and therefore `codegen_ssa`) assumes that there is a central
|
||||
@ -351,6 +393,8 @@ pub struct BuilderCursor {
|
||||
}
|
||||
|
||||
pub struct BuilderSpirv<'tcx> {
|
||||
source_map: &'tcx SourceMap,
|
||||
|
||||
builder: RefCell<Builder>,
|
||||
|
||||
// Bidirectional maps between `SpirvConst` and the ID of the defined global
|
||||
@ -359,14 +403,20 @@ pub struct BuilderSpirv<'tcx> {
|
||||
// allows getting that legality information without additional lookups.
|
||||
const_to_id: RefCell<FxHashMap<WithType<SpirvConst<'tcx>>, WithConstLegality<Word>>>,
|
||||
id_to_const: RefCell<FxHashMap<Word, WithConstLegality<SpirvConst<'tcx>>>>,
|
||||
string_cache: RefCell<FxHashMap<String, Word>>,
|
||||
|
||||
debug_file_cache: RefCell<FxHashMap<DebugFileKey, DebugFileSpirv>>,
|
||||
|
||||
enabled_capabilities: FxHashSet<Capability>,
|
||||
enabled_extensions: FxHashSet<Symbol>,
|
||||
}
|
||||
|
||||
impl<'tcx> BuilderSpirv<'tcx> {
|
||||
pub fn new(sym: &Symbols, target: &SpirvTarget, features: &[TargetFeature]) -> Self {
|
||||
pub fn new(
|
||||
source_map: &'tcx SourceMap,
|
||||
sym: &Symbols,
|
||||
target: &SpirvTarget,
|
||||
features: &[TargetFeature],
|
||||
) -> Self {
|
||||
let version = target.spirv_version();
|
||||
let memory_model = target.memory_model();
|
||||
|
||||
@ -427,10 +477,11 @@ impl<'tcx> BuilderSpirv<'tcx> {
|
||||
builder.memory_model(AddressingModel::Logical, memory_model);
|
||||
|
||||
Self {
|
||||
source_map,
|
||||
builder: RefCell::new(builder),
|
||||
const_to_id: Default::default(),
|
||||
id_to_const: Default::default(),
|
||||
string_cache: Default::default(),
|
||||
debug_file_cache: Default::default(),
|
||||
enabled_capabilities,
|
||||
enabled_extensions,
|
||||
}
|
||||
@ -637,15 +688,75 @@ impl<'tcx> BuilderSpirv<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_string(&self, s: String) -> Word {
|
||||
use std::collections::hash_map::Entry;
|
||||
match self.string_cache.borrow_mut().entry(s) {
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
let key = entry.key().clone();
|
||||
*entry.insert(self.builder(Default::default()).string(key))
|
||||
}
|
||||
}
|
||||
pub fn def_debug_file(&self, sf: Lrc<SourceFile>) -> DebugFileSpirv {
|
||||
*self
|
||||
.debug_file_cache
|
||||
.borrow_mut()
|
||||
.entry(DebugFileKey(sf))
|
||||
.or_insert_with_key(|DebugFileKey(sf)| {
|
||||
let mut builder = self.builder(Default::default());
|
||||
|
||||
// FIXME(eddyb) remapping might be really bad for being able to
|
||||
// load the sources the later, maybe it should be done at the
|
||||
// very end? (just before linking outputting the final SPIR-V)
|
||||
let file_name_op_string_id = builder.string(sf.name.prefer_remapped().to_string());
|
||||
|
||||
let file_contents = self
|
||||
.source_map
|
||||
.span_to_snippet(Span::with_root_ctxt(sf.start_pos, sf.end_pos))
|
||||
.ok();
|
||||
|
||||
// HACK(eddyb) this logic is duplicated from `spirt::spv::lift`.
|
||||
let op_source_and_continued_chunks = file_contents.as_ref().map(|contents| {
|
||||
// The maximum word count is `2**16 - 1`, the first word is
|
||||
// taken up by the opcode & word count, and one extra byte is
|
||||
// taken up by the nil byte at the end of the LiteralString.
|
||||
const MAX_OP_SOURCE_CONT_CONTENTS_LEN: usize = (0xffff - 1) * 4 - 1;
|
||||
|
||||
// `OpSource` has 3 more operands than `OpSourceContinued`,
|
||||
// and each of them take up exactly one word.
|
||||
const MAX_OP_SOURCE_CONTENTS_LEN: usize =
|
||||
MAX_OP_SOURCE_CONT_CONTENTS_LEN - 3 * 4;
|
||||
|
||||
let (op_source_str, mut all_op_source_continued_str) =
|
||||
contents.split_at(contents.len().min(MAX_OP_SOURCE_CONTENTS_LEN));
|
||||
|
||||
// FIXME(eddyb) `spirt::spv::lift` should use this.
|
||||
let all_op_source_continued_str_chunks = iter::from_fn(move || {
|
||||
let contents_rest = &mut all_op_source_continued_str;
|
||||
if contents_rest.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// FIXME(eddyb) test with UTF-8! this `split_at` should
|
||||
// actually take *less* than the full possible size, to
|
||||
// avoid cutting a UTF-8 sequence.
|
||||
let (cont_chunk, rest) = contents_rest
|
||||
.split_at(contents_rest.len().min(MAX_OP_SOURCE_CONT_CONTENTS_LEN));
|
||||
*contents_rest = rest;
|
||||
Some(cont_chunk)
|
||||
});
|
||||
(op_source_str, all_op_source_continued_str_chunks)
|
||||
});
|
||||
|
||||
if let Some((op_source_str, all_op_source_continued_str_chunks)) =
|
||||
op_source_and_continued_chunks
|
||||
{
|
||||
builder.source(
|
||||
SourceLanguage::Unknown,
|
||||
0,
|
||||
Some(file_name_op_string_id),
|
||||
Some(op_source_str),
|
||||
);
|
||||
for cont_chunk in all_op_source_continued_str_chunks {
|
||||
builder.source_continued(cont_chunk);
|
||||
}
|
||||
}
|
||||
|
||||
DebugFileSpirv {
|
||||
file_name_op_string_id,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_global_initializer(&self, global: Word, initializer: Word) {
|
||||
|
@ -117,7 +117,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
Self {
|
||||
tcx,
|
||||
codegen_unit,
|
||||
builder: BuilderSpirv::new(&sym, &target, &features),
|
||||
builder: BuilderSpirv::new(tcx.sess.source_map(), &sym, &target, &features),
|
||||
instances: Default::default(),
|
||||
function_parameter_values: Default::default(),
|
||||
type_cache: Default::default(),
|
||||
|
@ -5,6 +5,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_middle::bug;
|
||||
use std::collections::hash_map;
|
||||
|
||||
// FIXME(eddyb) consider deduplicating the `OpString` and `OpSource` created for
|
||||
// file-level debuginfo (but using SPIR-T for linking might be better?).
|
||||
|
||||
pub fn remove_duplicate_extensions(module: &mut Module) {
|
||||
let mut set = FxHashSet::default();
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
// compile-flags: -C target-feature=+RuntimeDescriptorArray,+ext:SPV_EXT_descriptor_indexing
|
||||
// compile-flags: -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
// compile-flags: -C target-feature=+RuntimeDescriptorArray,+ext:SPV_EXT_descriptor_indexing
|
||||
// compile-flags: -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
#![feature(adt_const_params)]
|
||||
|
@ -7,6 +7,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
#![feature(adt_const_params)]
|
||||
|
@ -17,6 +17,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C debuginfo=0 -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C debuginfo=0 -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
// build-pass
|
||||
// compile-flags: -C llvm-args=--disassemble-globals
|
||||
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
|
||||
// normalize-stderr-test "OpSource .*\n" -> ""
|
||||
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
|
||||
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user