mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2025-02-17 01:14:06 +00:00
Implement bool=i8 and some of the DeclareMethods API
This commit is contained in:
parent
ab6564e8b1
commit
a526109042
@ -1,7 +1,8 @@
|
||||
use crate::codegen_cx::CodegenCx;
|
||||
use rspirv::dr::Operand;
|
||||
use rspirv::spirv::{Decoration, StorageClass, Word};
|
||||
use rustc_middle::ty::{layout::TyAndLayout, TyKind};
|
||||
use rustc_middle::ty::{layout::TyAndLayout, Ty, TyKind};
|
||||
use rustc_target::abi::call::{FnAbi, PassMode};
|
||||
use rustc_target::abi::{Abi, FieldsShape, LayoutOf, Primitive, Scalar};
|
||||
use std::fmt;
|
||||
|
||||
@ -42,8 +43,6 @@ impl SpirvType {
|
||||
if let Some(&cached) = cx.type_cache.borrow().get(self) {
|
||||
return cached;
|
||||
}
|
||||
//let cached = cx.type_cache.borrow_mut().entry(self);
|
||||
// TODO: rspirv does a linear search to dedupe, probably want to cache here.
|
||||
let result = match *self {
|
||||
SpirvType::Void => cx.emit_global().type_void(),
|
||||
SpirvType::Bool => cx.emit_global().type_bool(),
|
||||
@ -190,6 +189,89 @@ impl fmt::Debug for SpirvTypePrinter<'_, '_, '_> {
|
||||
}
|
||||
}
|
||||
|
||||
// returns (function_type, return_type, argument_types)
|
||||
pub fn trans_fnabi<'spv, 'tcx>(
|
||||
cx: &CodegenCx<'spv, 'tcx>,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
) -> (Word, Word, Vec<Word>) {
|
||||
let mut argument_types = Vec::new();
|
||||
for arg in &fn_abi.args {
|
||||
let arg_type = match arg.mode {
|
||||
PassMode::Ignore => panic!(
|
||||
"TODO: Argument PassMode::Ignore not supported yet: {:?}",
|
||||
arg
|
||||
),
|
||||
PassMode::Direct(_arg_attributes) => trans_type_immediate(cx, arg.layout),
|
||||
PassMode::Pair(_arg_attributes_1, _arg_attributes_2) => {
|
||||
// TODO: Make this more efficient, don't generate struct
|
||||
let tuple = cx.lookup_type(trans_type(cx, arg.layout));
|
||||
let (left, right) = match tuple {
|
||||
SpirvType::Adt {
|
||||
ref field_types,
|
||||
field_offsets: _,
|
||||
} => {
|
||||
if let [left, right] = *field_types.as_slice() {
|
||||
(left, right)
|
||||
} else {
|
||||
panic!("PassMode::Pair did not produce tuple: {:?}", tuple)
|
||||
}
|
||||
}
|
||||
_ => panic!("PassMode::Pair did not produce tuple: {:?}", tuple),
|
||||
};
|
||||
argument_types.push(left);
|
||||
argument_types.push(right);
|
||||
continue;
|
||||
}
|
||||
PassMode::Cast(_cast_target) => trans_type(cx, arg.layout),
|
||||
// TODO: Deal with wide ptr?
|
||||
PassMode::Indirect(_arg_attributes, _wide_ptr_attrs) => {
|
||||
let pointee = trans_type(cx, arg.layout);
|
||||
SpirvType::Pointer {
|
||||
storage_class: StorageClass::Generic,
|
||||
pointee,
|
||||
}
|
||||
.def(cx)
|
||||
}
|
||||
};
|
||||
argument_types.push(arg_type);
|
||||
}
|
||||
// TODO: Other modes
|
||||
let return_type = match fn_abi.ret.mode {
|
||||
PassMode::Ignore => SpirvType::Void.def(cx),
|
||||
PassMode::Direct(_arg_attributes) => trans_type_immediate(cx, fn_abi.ret.layout),
|
||||
PassMode::Pair(_arg_attributes_1, _arg_attributes_2) => trans_type(cx, fn_abi.ret.layout),
|
||||
// TODO: Is this right?
|
||||
PassMode::Cast(_cast_target) => trans_type(cx, fn_abi.ret.layout),
|
||||
// TODO: Deal with wide ptr?
|
||||
PassMode::Indirect(_arg_attributes, _wide_ptr_attrs) => {
|
||||
let pointee = trans_type(cx, fn_abi.ret.layout);
|
||||
let pointer = SpirvType::Pointer {
|
||||
storage_class: StorageClass::Generic,
|
||||
pointee,
|
||||
}
|
||||
.def(cx);
|
||||
argument_types.push(pointer);
|
||||
SpirvType::Void.def(cx)
|
||||
}
|
||||
};
|
||||
|
||||
let function_type = SpirvType::Function {
|
||||
return_type,
|
||||
arguments: argument_types.clone(),
|
||||
}
|
||||
.def(cx);
|
||||
(function_type, return_type, argument_types)
|
||||
}
|
||||
|
||||
pub fn trans_type_immediate<'spv, 'tcx>(cx: &CodegenCx<'spv, 'tcx>, ty: TyAndLayout<'tcx>) -> Word {
|
||||
if let Abi::Scalar(ref scalar) = ty.abi {
|
||||
if scalar.is_bool() {
|
||||
return SpirvType::Bool.def(cx);
|
||||
}
|
||||
}
|
||||
trans_type(cx, ty)
|
||||
}
|
||||
|
||||
pub fn trans_type<'spv, 'tcx>(cx: &CodegenCx<'spv, 'tcx>, ty: TyAndLayout<'tcx>) -> Word {
|
||||
if ty.is_zst() {
|
||||
// An empty struct is zero-sized
|
||||
@ -236,20 +318,9 @@ fn trans_scalar<'spv, 'tcx>(
|
||||
pair_index: Option<usize>,
|
||||
) -> Word {
|
||||
match scalar.value {
|
||||
// TODO: Do we use scalar.valid_range?
|
||||
Primitive::Int(width, signedness) => {
|
||||
// let width_bits = width.size().bits() as u128;
|
||||
// let width_max_val = if width_bits == 128 {
|
||||
// u128::MAX
|
||||
// } else {
|
||||
// (1 << width_bits) - 1
|
||||
// };
|
||||
if scalar.valid_range == (0..=1) {
|
||||
SpirvType::Bool.def(cx)
|
||||
// } else if scalar.valid_range != (0..=width_max_val) {
|
||||
// TODO: Do we handle this specially?
|
||||
} else {
|
||||
SpirvType::Integer(width.size().bits() as u32, signedness).def(cx)
|
||||
}
|
||||
SpirvType::Integer(width.size().bits() as u32, signedness).def(cx)
|
||||
}
|
||||
Primitive::F32 => SpirvType::Float(32).def(cx),
|
||||
Primitive::F64 => SpirvType::Float(64).def(cx),
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::Builder;
|
||||
use crate::abi::SpirvType;
|
||||
use crate::builder_spirv::{BuilderCursor, SpirvValueExt};
|
||||
use rspirv::dr::Operand;
|
||||
use rspirv::spirv::StorageClass;
|
||||
use rustc_codegen_ssa::base::to_immediate;
|
||||
use rustc_codegen_ssa::common::{
|
||||
@ -69,7 +70,13 @@ impl<'a, 'spv, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'spv, 'tcx> {
|
||||
let emit = self.emit_with_cursor(cursor);
|
||||
let selected_function = emit.selected_function().unwrap();
|
||||
let selected_function = &emit.module_ref().functions[selected_function];
|
||||
selected_function.def.as_ref().unwrap().result_id.unwrap()
|
||||
let def_inst = selected_function.def.as_ref().unwrap();
|
||||
let def = def_inst.result_id.unwrap();
|
||||
let ty = match def_inst.operands[1] {
|
||||
Operand::IdRef(ty) => ty,
|
||||
ref other => panic!("Invalid operand to function inst: {}", other),
|
||||
};
|
||||
def.with_type(ty)
|
||||
};
|
||||
self.cursor = cursor;
|
||||
self.current_fn = current_fn;
|
||||
@ -77,7 +84,7 @@ 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 {
|
||||
let cursor_fn = cx.builder.select_function_by_id(llfn);
|
||||
let cursor_fn = cx.builder.select_function_by_id(llfn.def);
|
||||
let label = cx.emit_with_cursor(cursor_fn).begin_block(None).unwrap();
|
||||
let cursor = cx.builder.select_block_by_id(label);
|
||||
Self {
|
||||
@ -220,12 +227,12 @@ impl<'a, 'spv, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'spv, 'tcx> {
|
||||
|
||||
fn alloca(&mut self, ty: Self::Type, _align: Align) -> Self::Value {
|
||||
let ptr_ty = SpirvType::Pointer {
|
||||
storage_class: StorageClass::Function,
|
||||
storage_class: StorageClass::Generic,
|
||||
pointee: ty,
|
||||
}
|
||||
.def(self);
|
||||
self.emit()
|
||||
.variable(ptr_ty, None, StorageClass::Function, None)
|
||||
.variable(ptr_ty, None, StorageClass::Generic, None)
|
||||
.with_type(ptr_ty)
|
||||
}
|
||||
|
||||
@ -490,6 +497,10 @@ impl<'a, 'spv, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'spv, 'tcx> {
|
||||
}
|
||||
|
||||
fn intcast(&mut self, val: Self::Value, dest_ty: Self::Type, is_signed: bool) -> Self::Value {
|
||||
if val.ty == dest_ty {
|
||||
// I guess?
|
||||
return val;
|
||||
}
|
||||
match (self.lookup_type(val.ty), self.lookup_type(dest_ty)) {
|
||||
// sign change
|
||||
(
|
||||
@ -812,10 +823,16 @@ impl<'a, 'spv, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'spv, 'tcx> {
|
||||
if funclet.is_some() {
|
||||
panic!("TODO: Funclets are not supported");
|
||||
}
|
||||
let result_type = match self.lookup_type(llfn.ty) {
|
||||
SpirvType::Function { return_type, .. } => return_type,
|
||||
let (result_type, argument_types) = match self.lookup_type(llfn.ty) {
|
||||
SpirvType::Function {
|
||||
return_type,
|
||||
arguments,
|
||||
} => (return_type, arguments),
|
||||
ty => panic!("Calling non-function type: {:?}", ty),
|
||||
};
|
||||
for (argument, argument_type) in args.iter().zip(argument_types) {
|
||||
assert_ty_eq!(self, argument.ty, argument_type);
|
||||
}
|
||||
let args = args.iter().map(|arg| arg.def).collect::<Vec<_>>();
|
||||
self.emit()
|
||||
.function_call(result_type, None, llfn.def, args)
|
||||
|
@ -49,16 +49,22 @@ impl<'a, 'spv, 'tcx> Builder<'a, 'spv, 'tcx> {
|
||||
// "An OpAccessChain instruction is the equivalent of an LLVM getelementptr instruction where the first index element is zero."
|
||||
// https://github.com/gpuweb/gpuweb/issues/33
|
||||
let mut result_indices = Vec::with_capacity(indices.len() - 1);
|
||||
let /*mut*/ (storage_class, result_pointee_type) = match self.lookup_type(ptr.ty) {
|
||||
SpirvType::Pointer { storage_class, pointee } => (storage_class, pointee),
|
||||
let (storage_class, mut result_pointee_type) = match self.lookup_type(ptr.ty) {
|
||||
SpirvType::Pointer {
|
||||
storage_class,
|
||||
pointee,
|
||||
} => (storage_class, pointee),
|
||||
other_type => panic!("GEP first deref not implemented for type {:?}", other_type),
|
||||
};
|
||||
for index in indices.iter().cloned().skip(1) {
|
||||
result_indices.push(index.def);
|
||||
panic!(
|
||||
"GEP not implemented for type {:?}",
|
||||
self.lookup_type(result_pointee_type)
|
||||
);
|
||||
result_pointee_type = match self.lookup_type(result_pointee_type) {
|
||||
SpirvType::Array { element, count: _ } => element,
|
||||
_ => panic!(
|
||||
"GEP not implemented for type {:?}",
|
||||
self.debug_type(result_pointee_type)
|
||||
),
|
||||
};
|
||||
}
|
||||
let result_type = SpirvType::Pointer {
|
||||
storage_class,
|
||||
@ -173,7 +179,7 @@ impl<'a, 'spv, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'spv, 'tcx> {
|
||||
dst: PlaceRef<'tcx, Self::Value>,
|
||||
) {
|
||||
fn next<'a, 'spv, 'tcx>(bx: &mut Builder<'a, 'spv, 'tcx>, idx: &mut usize) -> SpirvValue {
|
||||
let val = bx.function_parameter_values.borrow()[&bx.current_fn][*idx];
|
||||
let val = bx.function_parameter_values.borrow()[&bx.current_fn.def][*idx];
|
||||
*idx += 1;
|
||||
val
|
||||
}
|
||||
@ -232,7 +238,7 @@ impl<'a, 'spv, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'spv, 'tcx> {
|
||||
}
|
||||
|
||||
fn get_param(&self, index: usize) -> Self::Value {
|
||||
self.function_parameter_values.borrow()[&self.current_fn][index]
|
||||
self.function_parameter_values.borrow()[&self.current_fn.def][index]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ impl ModuleSpirv {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, Default, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub struct SpirvValue {
|
||||
pub def: Word,
|
||||
pub ty: Word,
|
||||
|
@ -14,15 +14,14 @@ use rustc_middle::mir::interpret::Allocation;
|
||||
use rustc_middle::mir::mono::{CodegenUnit, Linkage, Visibility};
|
||||
use rustc_middle::mir::Body;
|
||||
use rustc_middle::ty::layout::{FnAbiExt, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout};
|
||||
use rustc_middle::ty::{Instance, PolyExistentialTraitRef};
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_mir::interpret::Scalar;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::{CrateNum, DefId};
|
||||
use rustc_span::source_map::{Span, DUMMY_SP};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::SourceFile;
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg};
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
use rustc_target::abi::{
|
||||
self, Abi, AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Size, TargetDataLayout,
|
||||
};
|
||||
@ -37,6 +36,8 @@ pub struct CodegenCx<'spv, 'tcx> {
|
||||
pub spirv_module: &'spv ModuleSpirv,
|
||||
/// Spir-v module builder
|
||||
pub builder: BuilderSpirv,
|
||||
/// Used for the DeclareMethods API (not sure what it is yet)
|
||||
pub declared_values: RefCell<HashMap<String, SpirvValue>>,
|
||||
/// Map from MIR function to spir-v function ID
|
||||
pub function_defs: RefCell<HashMap<Instance<'tcx>, SpirvValue>>,
|
||||
/// Map from function ID to parameter list
|
||||
@ -58,6 +59,7 @@ impl<'spv, 'tcx> CodegenCx<'spv, 'tcx> {
|
||||
codegen_unit,
|
||||
spirv_module,
|
||||
builder: BuilderSpirv::new(),
|
||||
declared_values: RefCell::new(HashMap::new()),
|
||||
function_defs: RefCell::new(HashMap::new()),
|
||||
function_parameter_values: RefCell::new(HashMap::new()),
|
||||
type_defs: RefCell::new(HashMap::new()),
|
||||
@ -79,11 +81,22 @@ impl<'spv, 'tcx> CodegenCx<'spv, 'tcx> {
|
||||
self.builder.builder(cursor)
|
||||
}
|
||||
|
||||
// returns (function_type, return_type, argument_types)
|
||||
pub fn trans_fnabi(&self, ty: &FnAbi<'tcx, Ty<'tcx>>) -> (Word, Word, Vec<Word>) {
|
||||
use crate::abi::trans_fnabi;
|
||||
trans_fnabi(self, ty)
|
||||
}
|
||||
|
||||
pub fn trans_type(&self, ty: TyAndLayout<'tcx>) -> Word {
|
||||
use crate::abi::trans_type;
|
||||
trans_type(self, ty)
|
||||
}
|
||||
|
||||
pub fn trans_type_immediate(&self, ty: TyAndLayout<'tcx>) -> Word {
|
||||
use crate::abi::trans_type_immediate;
|
||||
trans_type_immediate(self, ty)
|
||||
}
|
||||
|
||||
pub fn lookup_type(&self, ty: Word) -> SpirvType {
|
||||
self.type_defs
|
||||
.borrow()
|
||||
@ -110,7 +123,7 @@ impl<'spv, 'tcx> CodegenCx<'spv, 'tcx> {
|
||||
|
||||
impl<'spv, 'tcx> BackendTypes for CodegenCx<'spv, 'tcx> {
|
||||
type Value = SpirvValue;
|
||||
type Function = Word;
|
||||
type Function = SpirvValue;
|
||||
|
||||
type BasicBlock = Word;
|
||||
type Type = Word;
|
||||
@ -173,7 +186,7 @@ impl<'spv, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'spv, 'tcx> {
|
||||
}
|
||||
|
||||
fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type {
|
||||
self.trans_type(layout)
|
||||
self.trans_type_immediate(layout)
|
||||
}
|
||||
|
||||
fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool {
|
||||
@ -223,27 +236,30 @@ impl<'spv, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'spv, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'spv, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'spv, 'tcx> {
|
||||
// TODO: llvm types are signless, as in neither signed nor unsigned (I think?), so these are expected to be
|
||||
// signless. Do we want a SpirvType::Integer(_, Signless) to indicate the sign is unknown, and to do conversions at
|
||||
// appropriate places?
|
||||
fn type_i1(&self) -> Self::Type {
|
||||
SpirvType::Bool.def(self)
|
||||
}
|
||||
fn type_i8(&self) -> Self::Type {
|
||||
SpirvType::Integer(8, true).def(self)
|
||||
SpirvType::Integer(8, false).def(self)
|
||||
}
|
||||
fn type_i16(&self) -> Self::Type {
|
||||
SpirvType::Integer(16, true).def(self)
|
||||
SpirvType::Integer(16, false).def(self)
|
||||
}
|
||||
fn type_i32(&self) -> Self::Type {
|
||||
SpirvType::Integer(32, true).def(self)
|
||||
SpirvType::Integer(32, false).def(self)
|
||||
}
|
||||
fn type_i64(&self) -> Self::Type {
|
||||
SpirvType::Integer(64, true).def(self)
|
||||
SpirvType::Integer(64, false).def(self)
|
||||
}
|
||||
fn type_i128(&self) -> Self::Type {
|
||||
SpirvType::Integer(128, true).def(self)
|
||||
SpirvType::Integer(128, false).def(self)
|
||||
}
|
||||
fn type_isize(&self) -> Self::Type {
|
||||
let ptr_size = self.tcx.data_layout.pointer_size.bits() as u32;
|
||||
SpirvType::Integer(ptr_size, true).def(self)
|
||||
SpirvType::Integer(ptr_size, false).def(self)
|
||||
}
|
||||
|
||||
fn type_f32(&self) -> Self::Type {
|
||||
@ -344,6 +360,29 @@ impl<'spv, 'tcx> StaticMethods for CodegenCx<'spv, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_fn<'spv, 'tcx>(cx: &CodegenCx<'spv, 'tcx>, instance: Instance<'tcx>) -> SpirvValue {
|
||||
assert!(!instance.substs.needs_infer());
|
||||
assert!(!instance.substs.has_escaping_bound_vars());
|
||||
|
||||
if let Some(&func) = cx.function_defs.borrow().get(&instance) {
|
||||
return func;
|
||||
}
|
||||
|
||||
let sym = cx.tcx.symbol_name(instance).name;
|
||||
|
||||
let fn_abi = FnAbi::of_instance(cx, instance, &[]);
|
||||
|
||||
let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
|
||||
llfn
|
||||
} else {
|
||||
cx.declare_fn(&sym, &fn_abi)
|
||||
};
|
||||
|
||||
cx.function_defs.borrow_mut().insert(instance, llfn);
|
||||
|
||||
llfn
|
||||
}
|
||||
|
||||
impl<'spv, 'tcx> MiscMethods<'tcx> for CodegenCx<'spv, 'tcx> {
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn vtables(
|
||||
@ -357,11 +396,11 @@ impl<'spv, 'tcx> MiscMethods<'tcx> for CodegenCx<'spv, 'tcx> {
|
||||
}
|
||||
|
||||
fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function {
|
||||
self.function_defs.borrow()[&instance].def
|
||||
get_fn(self, instance)
|
||||
}
|
||||
|
||||
fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value {
|
||||
self.function_defs.borrow()[&instance]
|
||||
get_fn(self, instance)
|
||||
}
|
||||
|
||||
fn eh_personality(&self) -> Self::Value {
|
||||
@ -409,96 +448,11 @@ impl<'spv, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'spv, 'tcx> {
|
||||
instance: Instance<'tcx>,
|
||||
_linkage: Linkage,
|
||||
_visibility: Visibility,
|
||||
_symbol_name: &str,
|
||||
symbol_name: &str,
|
||||
) {
|
||||
let fn_abi = FnAbi::of_instance(self, instance, &[]);
|
||||
let mut argument_types = Vec::new();
|
||||
for arg in fn_abi.args {
|
||||
let arg_type = match arg.mode {
|
||||
PassMode::Ignore => panic!(
|
||||
"TODO: Argument PassMode::Ignore not supported yet: {:?}",
|
||||
arg
|
||||
),
|
||||
PassMode::Direct(_arg_attributes) => self.trans_type(arg.layout),
|
||||
PassMode::Pair(_arg_attributes_1, _arg_attributes_2) => {
|
||||
// TODO: Make this more efficient, don't generate struct
|
||||
let tuple = self.lookup_type(self.trans_type(arg.layout));
|
||||
let (left, right) = match tuple {
|
||||
SpirvType::Adt {
|
||||
ref field_types,
|
||||
field_offsets: _,
|
||||
} => {
|
||||
if let [left, right] = *field_types.as_slice() {
|
||||
(left, right)
|
||||
} else {
|
||||
panic!("PassMode::Pair did not produce tuple: {:?}", tuple)
|
||||
}
|
||||
}
|
||||
_ => panic!("PassMode::Pair did not produce tuple: {:?}", tuple),
|
||||
};
|
||||
argument_types.push(left);
|
||||
argument_types.push(right);
|
||||
continue;
|
||||
}
|
||||
PassMode::Cast(_cast_target) => self.trans_type(arg.layout),
|
||||
// TODO: Deal with wide ptr?
|
||||
PassMode::Indirect(_arg_attributes, _wide_ptr_attrs) => {
|
||||
let pointee = self.trans_type(arg.layout);
|
||||
SpirvType::Pointer {
|
||||
storage_class: StorageClass::Generic,
|
||||
pointee,
|
||||
}
|
||||
.def(self)
|
||||
}
|
||||
};
|
||||
argument_types.push(arg_type);
|
||||
}
|
||||
// TODO: Other modes
|
||||
let return_type = match fn_abi.ret.mode {
|
||||
PassMode::Ignore => SpirvType::Void.def(self),
|
||||
PassMode::Direct(_arg_attributes) => self.trans_type(fn_abi.ret.layout),
|
||||
PassMode::Pair(_arg_attributes_1, _arg_attributes_2) => {
|
||||
self.trans_type(fn_abi.ret.layout)
|
||||
}
|
||||
// TODO: Is this right?
|
||||
PassMode::Cast(_cast_target) => self.trans_type(fn_abi.ret.layout),
|
||||
// TODO: Deal with wide ptr?
|
||||
PassMode::Indirect(_arg_attributes, _wide_ptr_attrs) => {
|
||||
let pointee = self.trans_type(fn_abi.ret.layout);
|
||||
let pointer = SpirvType::Pointer {
|
||||
storage_class: StorageClass::Generic,
|
||||
pointee,
|
||||
}
|
||||
.def(self);
|
||||
argument_types.push(pointer);
|
||||
SpirvType::Void.def(self)
|
||||
}
|
||||
};
|
||||
let control = FunctionControl::NONE;
|
||||
let function_id = None;
|
||||
|
||||
let function_type = SpirvType::Function {
|
||||
return_type,
|
||||
arguments: argument_types.clone(),
|
||||
}
|
||||
.def(self);
|
||||
|
||||
let mut emit = self.emit_global();
|
||||
let fn_id = emit
|
||||
.begin_function(return_type, function_id, control, function_type)
|
||||
.unwrap();
|
||||
let parameter_values = argument_types
|
||||
.iter()
|
||||
.map(|&ty| emit.function_parameter(ty).unwrap().with_type(ty))
|
||||
.collect::<Vec<_>>();
|
||||
emit.end_function().unwrap();
|
||||
|
||||
self.function_defs
|
||||
.borrow_mut()
|
||||
.insert(instance, fn_id.with_type(function_type));
|
||||
self.function_parameter_values
|
||||
.borrow_mut()
|
||||
.insert(fn_id, parameter_values);
|
||||
let declared = self.declare_fn(symbol_name, &fn_abi);
|
||||
self.function_defs.borrow_mut().insert(instance, declared);
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,8 +465,30 @@ impl<'spv, 'tcx> DeclareMethods<'tcx> for CodegenCx<'spv, 'tcx> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn declare_fn(&self, _name: &str, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function {
|
||||
todo!()
|
||||
fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function {
|
||||
let control = FunctionControl::NONE;
|
||||
let function_id = None;
|
||||
|
||||
let (function_type, return_type, argument_types) = self.trans_fnabi(fn_abi);
|
||||
|
||||
let mut emit = self.emit_global();
|
||||
let fn_id = emit
|
||||
.begin_function(return_type, function_id, control, function_type)
|
||||
.unwrap();
|
||||
let parameter_values = argument_types
|
||||
.iter()
|
||||
.map(|&ty| emit.function_parameter(ty).unwrap().with_type(ty))
|
||||
.collect::<Vec<_>>();
|
||||
emit.end_function().unwrap();
|
||||
|
||||
self.function_parameter_values
|
||||
.borrow_mut()
|
||||
.insert(fn_id, parameter_values);
|
||||
let result = fn_id.with_type(function_type);
|
||||
self.declared_values
|
||||
.borrow_mut()
|
||||
.insert(name.to_string(), result);
|
||||
result
|
||||
}
|
||||
|
||||
fn define_global(&self, _name: &str, _ty: Self::Type) -> Option<Self::Value> {
|
||||
@ -523,8 +499,8 @@ impl<'spv, 'tcx> DeclareMethods<'tcx> for CodegenCx<'spv, 'tcx> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn get_declared_value(&self, _name: &str) -> Option<Self::Value> {
|
||||
todo!()
|
||||
fn get_declared_value(&self, name: &str) -> Option<Self::Value> {
|
||||
self.declared_values.borrow().get(name).copied()
|
||||
}
|
||||
|
||||
fn get_defined_value(&self, _name: &str) -> Option<Self::Value> {
|
||||
|
Loading…
Reference in New Issue
Block a user