Hash out rustc_codegen_ssa backend

This commit is contained in:
khyperia 2020-08-17 12:56:50 +02:00
parent 371fe3f4f7
commit 1124c47b52
6 changed files with 1550 additions and 11 deletions

0
rustc_codegen_spirv/run.sh Normal file → Executable file
View File

View File

@ -0,0 +1,568 @@
use super::Builder;
use rustc_codegen_ssa::common::{
AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope,
};
use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{BuilderMethods, OverflowOp};
use rustc_codegen_ssa::MemFlags;
use rustc_middle::ty::Ty;
use rustc_target::abi::{Align, Size};
use std::ops::Range;
impl<'a, 'spv, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'spv, 'tcx> {
fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &'b str) -> Self {
todo!()
}
fn with_cx(cx: &'a Self::CodegenCx) -> Self {
let spirv = rspirv::dr::Builder::new();
Self { spirv, cx }
}
fn build_sibling_block(&self, name: &str) -> Self {
todo!()
}
fn cx(&self) -> &Self::CodegenCx {
self.cx
}
fn llbb(&self) -> Self::BasicBlock {
todo!()
}
fn position_at_end(&mut self, llbb: Self::BasicBlock) {
todo!()
}
fn ret_void(&mut self) {
todo!()
}
fn ret(&mut self, v: Self::Value) {
todo!()
}
fn br(&mut self, dest: Self::BasicBlock) {
todo!()
}
fn cond_br(
&mut self,
cond: Self::Value,
then_llbb: Self::BasicBlock,
else_llbb: Self::BasicBlock,
) {
todo!()
}
fn switch(
&mut self,
v: Self::Value,
else_llbb: Self::BasicBlock,
cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock)>,
) {
todo!()
}
fn invoke(
&mut self,
llfn: Self::Value,
args: &[Self::Value],
then: Self::BasicBlock,
catch: Self::BasicBlock,
funclet: Option<&Self::Funclet>,
) -> Self::Value {
todo!()
}
fn unreachable(&mut self) {
todo!()
}
fn add(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fadd_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn sub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fsub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fsub_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn mul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fmul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fmul_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn udiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn exactudiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn sdiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn exactsdiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fdiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fdiv_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn urem(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn srem(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn frem(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn frem_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn shl(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn lshr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn ashr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn unchecked_ssub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn unchecked_usub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn unchecked_smul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn xor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn neg(&mut self, v: Self::Value) -> Self::Value {
todo!()
}
fn fneg(&mut self, v: Self::Value) -> Self::Value {
todo!()
}
fn not(&mut self, v: Self::Value) -> Self::Value {
todo!()
}
fn checked_binop(
&mut self,
oop: OverflowOp,
ty: Ty<'_>,
lhs: Self::Value,
rhs: Self::Value,
) -> (Self::Value, Self::Value) {
todo!()
}
fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value {
todo!()
}
fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value {
todo!()
}
fn array_alloca(&mut self, ty: Self::Type, len: Self::Value, align: Align) -> Self::Value {
todo!()
}
fn load(&mut self, ptr: Self::Value, align: Align) -> Self::Value {
todo!()
}
fn volatile_load(&mut self, ptr: Self::Value) -> Self::Value {
todo!()
}
fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> Self::Value {
todo!()
}
fn load_operand(
&mut self,
place: PlaceRef<'tcx, Self::Value>,
) -> OperandRef<'tcx, Self::Value> {
todo!()
}
/// Called for Rvalue::Repeat when the elem is neither a ZST nor optimizable using memset.
fn write_operand_repeatedly(
self,
elem: OperandRef<'tcx, Self::Value>,
count: u64,
dest: PlaceRef<'tcx, Self::Value>,
) -> Self {
todo!()
}
fn range_metadata(&mut self, load: Self::Value, range: Range<u128>) {
todo!()
}
fn nonnull_metadata(&mut self, load: Self::Value) {
todo!()
}
fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value {
todo!()
}
fn store_with_flags(
&mut self,
val: Self::Value,
ptr: Self::Value,
align: Align,
flags: MemFlags,
) -> Self::Value {
todo!()
}
fn atomic_store(
&mut self,
val: Self::Value,
ptr: Self::Value,
order: AtomicOrdering,
size: Size,
) {
todo!()
}
fn gep(&mut self, ptr: Self::Value, indices: &[Self::Value]) -> Self::Value {
todo!()
}
fn inbounds_gep(&mut self, ptr: Self::Value, indices: &[Self::Value]) -> Self::Value {
todo!()
}
fn struct_gep(&mut self, ptr: Self::Value, idx: u64) -> Self::Value {
todo!()
}
fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option<Self::Value> {
todo!()
}
fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option<Self::Value> {
todo!()
}
fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn sitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn fptrunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn fpext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn ptrtoint(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn inttoptr(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn bitcast(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn intcast(&mut self, val: Self::Value, dest_ty: Self::Type, is_signed: bool) -> Self::Value {
todo!()
}
fn pointercast(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
todo!()
}
fn memcpy(
&mut self,
dst: Self::Value,
dst_align: Align,
src: Self::Value,
src_align: Align,
size: Self::Value,
flags: MemFlags,
) {
todo!()
}
fn memmove(
&mut self,
dst: Self::Value,
dst_align: Align,
src: Self::Value,
src_align: Align,
size: Self::Value,
flags: MemFlags,
) {
todo!()
}
fn memset(
&mut self,
ptr: Self::Value,
fill_byte: Self::Value,
size: Self::Value,
align: Align,
flags: MemFlags,
) {
todo!()
}
fn select(
&mut self,
cond: Self::Value,
then_val: Self::Value,
else_val: Self::Value,
) -> Self::Value {
todo!()
}
fn va_arg(&mut self, list: Self::Value, ty: Self::Type) -> Self::Value {
todo!()
}
fn extract_element(&mut self, vec: Self::Value, idx: Self::Value) -> Self::Value {
todo!()
}
fn vector_splat(&mut self, num_elts: usize, elt: Self::Value) -> Self::Value {
todo!()
}
fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value {
todo!()
}
fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value {
todo!()
}
fn landing_pad(
&mut self,
ty: Self::Type,
pers_fn: Self::Value,
num_clauses: usize,
) -> Self::Value {
todo!()
}
fn set_cleanup(&mut self, landing_pad: Self::Value) {
todo!()
}
fn resume(&mut self, exn: Self::Value) -> Self::Value {
todo!()
}
fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet {
todo!()
}
fn cleanup_ret(
&mut self,
funclet: &Self::Funclet,
unwind: Option<Self::BasicBlock>,
) -> Self::Value {
todo!()
}
fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet {
todo!()
}
fn catch_switch(
&mut self,
parent: Option<Self::Value>,
unwind: Option<Self::BasicBlock>,
num_handlers: usize,
) -> Self::Value {
todo!()
}
fn add_handler(&mut self, catch_switch: Self::Value, handler: Self::BasicBlock) {
todo!()
}
fn set_personality_fn(&mut self, personality: Self::Value) {
todo!()
}
fn atomic_cmpxchg(
&mut self,
dst: Self::Value,
cmp: Self::Value,
src: Self::Value,
order: AtomicOrdering,
failure_order: AtomicOrdering,
weak: bool,
) -> Self::Value {
todo!()
}
fn atomic_rmw(
&mut self,
op: AtomicRmwBinOp,
dst: Self::Value,
src: Self::Value,
order: AtomicOrdering,
) -> Self::Value {
todo!()
}
fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope) {
todo!()
}
fn set_invariant_load(&mut self, load: Self::Value) {
todo!()
}
/// Called for `StorageLive`
fn lifetime_start(&mut self, ptr: Self::Value, size: Size) {
todo!()
}
/// Called for `StorageDead`
fn lifetime_end(&mut self, ptr: Self::Value, size: Size) {
todo!()
}
fn instrprof_increment(
&mut self,
fn_name: Self::Value,
hash: Self::Value,
num_counters: Self::Value,
index: Self::Value,
) -> Self::Value {
todo!()
}
fn call(
&mut self,
llfn: Self::Value,
args: &[Self::Value],
funclet: Option<&Self::Funclet>,
) -> Self::Value {
todo!()
}
fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
todo!()
}
unsafe fn delete_basic_block(&mut self, bb: Self::BasicBlock) {
todo!()
}
fn do_not_inline(&mut self, llret: Self::Value) {
todo!()
}
}

View File

@ -0,0 +1,246 @@
mod builder_methods;
use crate::codegen_cx::CodegenCx;
use rustc_ast::ast::InlineAsmOptions;
use rustc_ast::ast::InlineAsmTemplatePiece;
use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::InlineAsmOperandRef;
use rustc_codegen_ssa::traits::{
AbiBuilderMethods, ArgAbiMethods, AsmBuilderMethods, BackendTypes, CoverageInfoBuilderMethods,
DebugInfoBuilderMethods, HasCodegen, IntrinsicCallMethods, StaticBuilderMethods,
};
use rustc_hir::LlvmInlineAsmInner;
use rustc_middle::mir::Operand;
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::Instance;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;
use rustc_target::abi::call::ArgAbi;
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout};
use rustc_target::spec::{HasTargetSpec, Target};
use std::ops::Deref;
pub struct Builder<'a, 'spv, 'tcx> {
pub spirv: rspirv::dr::Builder,
cx: &'a CodegenCx<'spv, 'tcx>,
}
impl<'a, 'spv, 'tcx> Deref for Builder<'a, 'spv, 'tcx> {
type Target = CodegenCx<'spv, 'tcx>;
fn deref(&self) -> &<Self as std::ops::Deref>::Target {
self.cx
}
}
impl<'a, 'spv, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'spv, 'tcx> {
fn add_counter_region(
&mut self,
_: rustc_middle::ty::Instance<'tcx>,
_: u64,
_: u32,
_: u32,
_: u32,
) {
todo!()
}
fn add_counter_expression_region(
&mut self,
_: rustc_middle::ty::Instance<'tcx>,
_: u32,
_: u32,
_: rustc_codegen_ssa::coverageinfo::CounterOp,
_: u32,
_: u32,
_: u32,
) {
todo!()
}
fn add_unreachable_region(&mut self, _: rustc_middle::ty::Instance<'tcx>, _: u32, _: u32) {
todo!()
}
}
impl<'a, 'spv, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'spv, 'tcx> {
fn dbg_var_addr(
&mut self,
dbg_var: Self::DIVariable,
scope_metadata: Self::DIScope,
variable_alloca: Self::Value,
direct_offset: Size,
// NB: each offset implies a deref (i.e. they're steps in a pointer chain).
indirect_offsets: &[Size],
span: Span,
) {
todo!()
}
fn set_source_location(&mut self, scope: Self::DIScope, span: Span) {
todo!()
}
fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
todo!()
}
fn set_var_name(&mut self, value: Self::Value, name: &str) {
todo!()
}
}
impl<'a, 'spv, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'spv, 'tcx> {
fn store_fn_arg(
&mut self,
arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
idx: &mut usize,
dst: PlaceRef<'tcx, Self::Value>,
) {
todo!()
}
fn store_arg(
&mut self,
arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
val: Self::Value,
dst: PlaceRef<'tcx, Self::Value>,
) {
todo!()
}
fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type {
todo!()
}
}
impl<'a, 'spv, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'spv, 'tcx> {
fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value) {
todo!()
}
fn get_param(&self, index: usize) -> Self::Value {
todo!()
}
}
impl<'a, 'spv, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'spv, 'tcx> {
fn codegen_intrinsic_call(
&mut self,
instance: Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, Self::Value>],
llresult: Self::Value,
span: Span,
caller_instance: Instance<'tcx>,
) {
todo!()
}
fn is_codegen_intrinsic(
&mut self,
intrinsic: Symbol,
args: &Vec<Operand<'tcx>>,
caller_instance: Instance<'tcx>,
) -> bool {
todo!()
}
fn abort(&mut self) {
todo!()
}
fn assume(&mut self, val: Self::Value) {
todo!()
}
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value {
todo!()
}
fn sideeffect(&mut self) {
todo!()
}
fn va_start(&mut self, val: Self::Value) -> Self::Value {
todo!()
}
fn va_end(&mut self, val: Self::Value) -> Self::Value {
todo!()
}
}
impl<'a, 'spv, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'spv, 'tcx> {
fn codegen_llvm_inline_asm(
&mut self,
ia: &LlvmInlineAsmInner,
outputs: Vec<PlaceRef<'tcx, Self::Value>>,
inputs: Vec<Self::Value>,
span: Span,
) -> bool {
todo!()
}
fn codegen_inline_asm(
&mut self,
template: &[InlineAsmTemplatePiece],
operands: &[InlineAsmOperandRef<'tcx, Self>],
options: InlineAsmOptions,
line_spans: &[Span],
) {
todo!()
}
}
impl<'a, 'spv, 'tcx> StaticBuilderMethods for Builder<'a, 'spv, 'tcx> {
fn get_static(&mut self, def_id: DefId) -> Self::Value {
todo!()
}
}
impl<'a, 'spv, 'tcx> BackendTypes for Builder<'a, 'spv, 'tcx> {
type Value = <CodegenCx<'spv, 'tcx> as BackendTypes>::Value;
type Function = <CodegenCx<'spv, 'tcx> as BackendTypes>::Function;
type BasicBlock = <CodegenCx<'spv, 'tcx> as BackendTypes>::BasicBlock;
type Type = <CodegenCx<'spv, 'tcx> as BackendTypes>::Type;
type Funclet = <CodegenCx<'spv, 'tcx> as BackendTypes>::Funclet;
type DIScope = <CodegenCx<'spv, 'tcx> as BackendTypes>::DIScope;
type DIVariable = <CodegenCx<'spv, 'tcx> as BackendTypes>::DIVariable;
}
impl<'a, 'spv, 'tcx> HasCodegen<'tcx> for Builder<'a, 'spv, 'tcx> {
type CodegenCx = CodegenCx<'spv, 'tcx>;
}
impl<'a, 'spv, 'tcx> HasParamEnv<'tcx> for Builder<'a, 'spv, 'tcx> {
fn param_env(&self) -> ParamEnv<'tcx> {
self.cx.param_env()
}
}
impl<'a, 'spv, 'tcx> HasTargetSpec for Builder<'a, 'spv, 'tcx> {
fn target_spec(&self) -> &Target {
&self.cx.target_spec()
}
}
impl<'a, 'spv, 'tcx> HasTyCtxt<'tcx> for Builder<'a, 'spv, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.cx.tcx
}
}
impl<'a, 'spv, 'tcx> HasDataLayout for Builder<'a, 'spv, 'tcx> {
fn data_layout(&self) -> &TargetDataLayout {
self.cx.data_layout()
}
}
impl<'a, 'spv, 'tcx> LayoutOf for Builder<'a, 'spv, 'tcx> {
type Ty = Ty<'tcx>;
type TyAndLayout = TyAndLayout<'tcx>;
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
self.cx.layout_of(ty)
}
}

View File

@ -0,0 +1,465 @@
use crate::things::ModuleSpirv;
use rspirv::spirv::Word;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::mir::debuginfo::FunctionDebugContext;
use rustc_codegen_ssa::mir::debuginfo::VariableKind;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{
AsmMethods, BackendTypes, BaseTypeMethods, ConstMethods, CoverageInfoMethods, DebugInfoMethods,
DeclareMethods, LayoutTypeMethods, MiscMethods, PreDefineMethods, StaticMethods,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::GlobalAsm;
use rustc_middle::mir::interpret::Allocation;
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::mir::mono::Linkage;
use rustc_middle::mir::mono::Visibility;
use rustc_middle::mir::Body;
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout};
use rustc_middle::ty::Instance;
use rustc_middle::ty::PolyExistentialTraitRef;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_mir::interpret::Scalar;
use rustc_session::Session;
use rustc_span::def_id::CrateNum;
use rustc_span::def_id::DefId;
use rustc_span::source_map::{Span, DUMMY_SP};
use rustc_span::symbol::Symbol;
use rustc_span::SourceFile;
use rustc_target::abi;
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
use rustc_target::abi::AddressSpace;
use rustc_target::abi::Align;
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout};
use rustc_target::spec::{HasTargetSpec, Target};
use std::cell::RefCell;
pub struct CodegenCx<'spv, 'tcx> {
pub tcx: TyCtxt<'tcx>,
pub codegen_unit: &'tcx CodegenUnit<'tcx>,
pub spirv_module: &'spv ModuleSpirv,
}
impl<'spv, 'tcx> CodegenCx<'spv, 'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
codegen_unit: &'tcx CodegenUnit<'tcx>,
spirv_module: &'spv ModuleSpirv,
) -> Self {
Self {
tcx,
codegen_unit,
spirv_module,
}
}
}
impl<'spv, 'tcx> BackendTypes for CodegenCx<'spv, 'tcx> {
type Value = Word;
type Function = Word;
type BasicBlock = Word;
type Type = Word;
// Funclet: A structure representing an active landing pad for the duration of a basic block. (??)
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/common/struct.Funclet.html
type Funclet = ();
type DIScope = ();
type DIVariable = ();
}
impl<'spv, 'tcx> LayoutOf for CodegenCx<'spv, 'tcx> {
type Ty = Ty<'tcx>;
type TyAndLayout = TyAndLayout<'tcx>;
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
self.spanned_layout_of(ty, DUMMY_SP)
}
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::TyAndLayout {
self.tcx
.layout_of(ParamEnv::reveal_all().and(ty))
.unwrap_or_else(|e| {
if let LayoutError::SizeOverflow(_) = e {
self.tcx.sess.span_fatal(span, &e.to_string())
} else {
panic!("failed to get layout for `{}`: {}", ty, e)
}
})
}
}
impl<'spv, 'tcx> HasTyCtxt<'tcx> for CodegenCx<'spv, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
}
impl<'spv, 'tcx> HasDataLayout for CodegenCx<'spv, 'tcx> {
fn data_layout(&self) -> &TargetDataLayout {
&self.tcx.data_layout
}
}
impl<'spv, 'tcx> HasTargetSpec for CodegenCx<'spv, 'tcx> {
fn target_spec(&self) -> &Target {
&self.tcx.sess.target.target
}
}
impl<'spv, 'tcx> HasParamEnv<'tcx> for CodegenCx<'spv, 'tcx> {
fn param_env(&self) -> ParamEnv<'tcx> {
ParamEnv::reveal_all()
}
}
impl<'spv, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type {
todo!()
}
fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type {
todo!()
}
fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool {
todo!()
}
fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool {
todo!()
}
fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 {
todo!()
}
fn scalar_pair_element_backend_type(
&self,
layout: TyAndLayout<'tcx>,
index: usize,
immediate: bool,
) -> Self::Type {
todo!()
}
fn cast_backend_type(&self, ty: &CastTarget) -> Self::Type {
todo!()
}
fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type {
todo!()
}
fn reg_backend_type(&self, ty: &Reg) -> Self::Type {
todo!()
}
}
impl<'spv, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn type_i1(&self) -> Self::Type {
todo!()
}
fn type_i8(&self) -> Self::Type {
todo!()
}
fn type_i16(&self) -> Self::Type {
todo!()
}
fn type_i32(&self) -> Self::Type {
todo!()
}
fn type_i64(&self) -> Self::Type {
todo!()
}
fn type_i128(&self) -> Self::Type {
todo!()
}
fn type_isize(&self) -> Self::Type {
todo!()
}
fn type_f32(&self) -> Self::Type {
todo!()
}
fn type_f64(&self) -> Self::Type {
todo!()
}
fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type {
todo!()
}
fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type {
todo!()
}
fn type_kind(&self, ty: Self::Type) -> TypeKind {
todo!()
}
fn type_ptr_to(&self, ty: Self::Type) -> Self::Type {
todo!()
}
fn type_ptr_to_ext(&self, ty: Self::Type, address_space: AddressSpace) -> Self::Type {
todo!()
}
fn element_type(&self, ty: Self::Type) -> Self::Type {
todo!()
}
/// Returns the number of elements in `self` if it is a LLVM vector type.
fn vector_length(&self, ty: Self::Type) -> usize {
todo!()
}
fn float_width(&self, ty: Self::Type) -> usize {
todo!()
}
/// Retrieves the bit width of the integer type `self`.
fn int_width(&self, ty: Self::Type) -> u64 {
todo!()
}
fn val_ty(&self, v: Self::Value) -> Self::Type {
todo!()
}
}
impl<'spv, 'tcx> StaticMethods for CodegenCx<'spv, 'tcx> {
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value {
todo!()
}
fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
todo!()
}
/// Mark the given global value as "used", to prevent a backend from potentially removing a
/// static variable that may otherwise appear unused.
///
/// Static variables in Rust can be annotated with the `#[used]` attribute to direct the `rustc`
/// compiler to mark the variable as a "used global".
fn add_used_global(&self, global: Self::Value) {
todo!()
}
}
impl<'spv, 'tcx> MiscMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn vtables(
&self,
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), Self::Value>> {
todo!()
}
fn check_overflow(&self) -> bool {
todo!()
}
fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function {
todo!()
}
fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value {
todo!()
}
fn eh_personality(&self) -> Self::Value {
todo!()
}
fn sess(&self) -> &Session {
&self.tcx.sess
}
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
self.codegen_unit
}
fn used_statics(&self) -> &RefCell<Vec<Self::Value>> {
todo!()
}
fn set_frame_pointer_elimination(&self, llfn: Self::Function) {
todo!()
}
fn apply_target_cpu_attr(&self, llfn: Self::Function) {
todo!()
}
fn create_used_variable(&self) {
todo!()
}
}
impl<'spv, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn predefine_static(
&self,
def_id: DefId,
linkage: Linkage,
visibility: Visibility,
symbol_name: &str,
) {
todo!()
}
fn predefine_fn(
&self,
instance: Instance<'tcx>,
linkage: Linkage,
visibility: Visibility,
symbol_name: &str,
) {
todo!()
}
}
impl<'spv, 'tcx> DeclareMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn declare_global(&self, name: &str, ty: Self::Type) -> Self::Value {
todo!()
}
fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Function {
todo!()
}
fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function {
todo!()
}
fn define_global(&self, name: &str, ty: Self::Type) -> Option<Self::Value> {
todo!()
}
fn define_private_global(&self, ty: Self::Type) -> Self::Value {
todo!()
}
fn get_declared_value(&self, name: &str) -> Option<Self::Value> {
todo!()
}
fn get_defined_value(&self, name: &str) -> Option<Self::Value> {
todo!()
}
}
impl<'spv, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn create_vtable_metadata(&self, ty: Ty<'tcx>, vtable: Self::Value) {
todo!()
}
fn create_function_debug_context(
&self,
instance: Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
llfn: Self::Function,
mir: &Body<'_>,
) -> Option<FunctionDebugContext<Self::DIScope>> {
todo!()
}
fn extend_scope_to_file(
&self,
scope_metadata: Self::DIScope,
file: &SourceFile,
defining_crate: CrateNum,
) -> Self::DIScope {
todo!()
}
fn debuginfo_finalize(&self) {
todo!()
}
fn create_dbg_var(
&self,
dbg_context: &FunctionDebugContext<Self::DIScope>,
variable_name: Symbol,
variable_type: Ty<'tcx>,
scope_metadata: Self::DIScope,
variable_kind: VariableKind,
span: Span,
) -> Self::DIVariable {
todo!()
}
}
impl<'spv, 'tcx> CoverageInfoMethods for CodegenCx<'spv, 'tcx> {
fn coverageinfo_finalize(&self) {
todo!()
}
}
impl<'spv, 'tcx> ConstMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn const_null(&self, t: Self::Type) -> Self::Value {
todo!()
}
fn const_undef(&self, t: Self::Type) -> Self::Value {
todo!()
}
fn const_int(&self, t: Self::Type, i: i64) -> Self::Value {
todo!()
}
fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value {
todo!()
}
fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value {
todo!()
}
fn const_bool(&self, val: bool) -> Self::Value {
todo!()
}
fn const_i32(&self, i: i32) -> Self::Value {
todo!()
}
fn const_u32(&self, i: u32) -> Self::Value {
todo!()
}
fn const_u64(&self, i: u64) -> Self::Value {
todo!()
}
fn const_usize(&self, i: u64) -> Self::Value {
todo!()
}
fn const_u8(&self, i: u8) -> Self::Value {
todo!()
}
fn const_real(&self, t: Self::Type, val: f64) -> Self::Value {
todo!()
}
fn const_str(&self, s: Symbol) -> (Self::Value, Self::Value) {
todo!()
}
fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value {
todo!()
}
fn const_to_opt_uint(&self, v: Self::Value) -> Option<u64> {
todo!()
}
fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option<u128> {
todo!()
}
fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value {
todo!()
}
fn from_const_alloc(
&self,
layout: TyAndLayout<'tcx>,
alloc: &Allocation,
offset: Size,
) -> PlaceRef<'tcx, Self::Value> {
todo!()
}
fn const_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
todo!()
}
}
impl<'spv, 'tcx> AsmMethods for CodegenCx<'spv, 'tcx> {
fn codegen_global_asm(&self, ga: &GlobalAsm) {
todo!()
}
}

View File

@ -1,37 +1,52 @@
#![feature(rustc_private)]
#![feature(or_insert_with_key)]
extern crate rustc_ast;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_hir;
extern crate rustc_interface;
extern crate rustc_middle;
extern crate rustc_mir;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target;
extern crate rustc_interface;
extern crate rustc_driver;
use rustc_codegen_ssa::traits::CodegenBackend;
mod builder;
mod codegen_cx;
mod ctx;
mod things;
mod trans;
use builder::Builder;
use codegen_cx::CodegenCx;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind};
use rustc_data_structures::owning_ref::OwningRef;
use rustc_data_structures::rustc_erase_owner;
use rustc_data_structures::sync::MetadataRef;
use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::DepGraph;
use rustc_errors::{ErrorReported, FatalError, Handler};
use rustc_middle::dep_graph::{DepGraph, WorkProduct};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::OutputFilenames;
use rustc_session::config::{OptLevel, OutputFilenames};
use rustc_session::Session;
use rustc_span::Symbol;
use rustc_target::spec::Target;
use std::any::Any;
use std::path::Path;
mod ctx;
mod trans;
use std::sync::Arc;
use things::{ModuleSpirv, SpirvModuleBuffer, SprivThinBuffer};
#[cfg(test)]
#[path = "../test/lib.rs"]
@ -156,10 +171,225 @@ impl CodegenBackend for TheBackend {
}
}
/// This is the entrypoint for a hot plugged rustc_codegen_llvm
#[derive(Clone)]
struct SsaBackend;
impl CodegenBackend for SsaBackend {
fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
Box::new(NoLlvmMetadataLoader)
}
fn provide(&self, providers: &mut Providers) {
rustc_symbol_mangling::provide(providers);
providers.supported_target_features = |_tcx, _cnum| {
Default::default() // Just a dummy
};
providers.is_reachable_non_generic = |_tcx, _defid| true;
providers.exported_symbols = |_tcx, _crate| &[];
}
fn provide_extern(&self, providers: &mut Providers) {
providers.is_reachable_non_generic = |_tcx, _defid| true;
}
fn codegen_crate<'tcx>(
&self,
tcx: rustc_middle::ty::TyCtxt<'tcx>,
metadata: rustc_middle::middle::cstore::EncodedMetadata,
need_metadata_module: bool,
) -> Box<dyn Any> {
Box::new(rustc_codegen_ssa::base::codegen_crate(
SsaBackend,
tcx,
metadata,
need_metadata_module,
))
}
fn join_codegen(
&self,
ongoing_codegen: Box<dyn Any>,
sess: &Session,
_dep_graph: &DepGraph,
) -> Result<Box<dyn Any>, ErrorReported> {
let (codegen_results, _work_products) = ongoing_codegen
.downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<SsaBackend>>()
.expect("Expected SpirvCodegenBackend's OngoingCodegen, found Box<Any>")
.join(sess);
if sess.opts.debugging_opts.incremental_info {
rustc_codegen_ssa::back::write::dump_incremental_data(&codegen_results);
}
// sess.time("serialize_work_products", move || {
// rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
// });
sess.compile_status()?;
Ok(Box::new(codegen_results))
}
fn link(
&self,
_sess: &Session,
codegen_results: Box<dyn Any>,
_outputs: &OutputFilenames,
) -> Result<(), ErrorReported> {
let _codegen_results = codegen_results
.downcast::<CodegenResults>()
.expect("Expected CodegenResults, found Box<Any>");
// TODO: see rustc_codegen_llvm for example of implementation
Ok(())
}
}
impl WriteBackendMethods for SsaBackend {
type Module = ModuleSpirv;
type TargetMachine = ();
type ModuleBuffer = SpirvModuleBuffer;
type Context = ();
type ThinData = ();
type ThinBuffer = SprivThinBuffer;
fn run_fat_lto(
_: &CodegenContext<Self>,
_: Vec<FatLTOInput<Self>>,
_: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<LtoModuleCodegen<Self>, FatalError> {
todo!()
}
fn run_thin_lto(
_: &CodegenContext<Self>,
_: Vec<(String, Self::ThinBuffer)>,
_: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
todo!()
}
fn print_pass_timings(&self) {
todo!()
}
unsafe fn optimize(
_: &CodegenContext<Self>,
_: &Handler,
_: &ModuleCodegen<Self::Module>,
_: &ModuleConfig,
) -> Result<(), FatalError> {
todo!()
}
unsafe fn optimize_thin(
_: &CodegenContext<Self>,
_: &mut ThinModule<Self>,
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
todo!()
}
unsafe fn codegen(
_: &CodegenContext<Self>,
_: &Handler,
_: ModuleCodegen<Self::Module>,
_: &ModuleConfig,
) -> Result<CompiledModule, FatalError> {
todo!()
}
fn prepare_thin(_: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
todo!()
}
fn serialize_module(_: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
todo!()
}
fn run_lto_pass_manager(
_: &CodegenContext<Self>,
_: &ModuleCodegen<Self::Module>,
_: &ModuleConfig,
_: bool,
) {
todo!()
}
}
impl ExtraBackendMethods for SsaBackend {
fn new_metadata(&self, _: TyCtxt<'_>, _: &str) -> Self::Module {
todo!()
}
fn write_compressed_metadata<'tcx>(
&self,
_: TyCtxt<'tcx>,
_: &EncodedMetadata,
_: &mut Self::Module,
) {
todo!()
}
fn codegen_allocator<'tcx>(&self, _: TyCtxt<'tcx>, _: &mut Self::Module, _: AllocatorKind) {
todo!()
}
fn compile_codegen_unit(
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
) -> (ModuleCodegen<Self::Module>, u64) {
// TODO: Do dep_graph stuff
let cgu = tcx.codegen_unit(cgu_name);
let spirv_module = ModuleSpirv::new(tcx, &cgu_name.as_str());
{
let cx = CodegenCx::new(tcx, cgu, &spirv_module);
let mono_items = cx.codegen_unit.items_in_deterministic_order(cx.tcx);
for &(mono_item, (linkage, visibility)) in &mono_items {
mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility);
}
// ... and now that we have everything pre-defined, fill out those definitions.
for &(mono_item, _) in &mono_items {
mono_item.define::<Builder<'_, '_, '_>>(&cx);
}
if let Some(entry) = maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx) {
// attributes::sanitize(&cx, SanitizerSet::empty(), entry);
}
}
(
ModuleCodegen {
name: cgu_name.to_string(),
module_llvm: spirv_module,
kind: ModuleKind::Regular,
},
0,
)
}
fn target_machine_factory(
&self,
_: &Session,
_: OptLevel,
) -> Arc<dyn Fn() -> Result<Self::TargetMachine, String> + Send + Sync + 'static> {
Arc::new(|| Ok(()))
}
fn target_cpu<'b>(&self, _: &'b Session) -> &'b str {
todo!()
}
}
/// This is the entrypoint for a hot plugged rustc_codegen_spirv
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
Box::new(TheBackend)
Box::new(SsaBackend)
}
// https://github.com/bjorn3/rustc_codegen_cranelift/blob/1b8df386aa72bc3dacb803f7d4deb4eadd63b56f/src/base.rs

View File

@ -0,0 +1,30 @@
use crate::ctx::type_tracker::SpirvType;
use rspirv::spirv::Word;
use rustc_codegen_ssa::traits::{ModuleBufferMethods, ThinBufferMethods};
use rustc_middle::ty::TyCtxt;
// uncategorized things, should be put into modules eventually
pub struct SpirvModuleBuffer;
impl ModuleBufferMethods for SpirvModuleBuffer {
fn data(&self) -> &[u8] {
todo!()
}
}
pub struct SprivThinBuffer;
impl ThinBufferMethods for SprivThinBuffer {
fn data(&self) -> &[u8] {
todo!()
}
}
pub struct ModuleSpirv {}
impl ModuleSpirv {
pub fn new<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: &str) -> Self {
Self {}
}
}