Extension instructions

This commit is contained in:
khyperia 2020-09-08 16:21:55 +02:00
parent 3a9d6f87ca
commit 913e19f696
8 changed files with 108 additions and 2 deletions

View File

@ -12,5 +12,5 @@ pushd build_libcore_test
# Use wasm32 because it's a relatively simple platform - if the x86 libcore is used, there's all sorts of "feature sse2 # Use wasm32 because it's a relatively simple platform - if the x86 libcore is used, there's all sorts of "feature sse2
# not found" and the like, and our spirv backend is never reached. With wasm32, it at least gets reached. # not found" and the like, and our spirv backend is never reached. With wasm32, it at least gets reached.
# (We probably want to add our own target eventually) # (We probably want to add our own target eventually)
xargo build --target wasm32-unknown-unknown -Ccodegen-units=1 xargo build --target wasm32-unknown-unknown
popd popd

View File

@ -0,0 +1 @@
/target/

View File

@ -0,0 +1,10 @@
#![no_std]
use core::panic::PanicInfo;
pub fn screaming_bananans() {}
#[panic_handler]
fn panic(_: &PanicInfo) -> ! {
loop {}
}

View File

@ -1 +0,0 @@
fn main() {}

View File

@ -0,0 +1,42 @@
use super::Builder;
use crate::builder_spirv::{SpirvValue, SpirvValueExt};
use rspirv::dr::Operand;
use rspirv::spirv::{GLOp, Word};
const GLSL_STD_450: &str = "GLSL.std.450";
/// Manager for OpExtInst/OpExtImport instructions
#[derive(Default)]
pub struct ExtInst {
glsl: Option<Word>,
}
impl ExtInst {
pub fn import_glsl<'a, 'tcx>(&mut self, bx: &Builder<'a, 'tcx>) -> Word {
match self.glsl {
Some(id) => id,
None => {
let id = bx.emit_global().ext_inst_import(GLSL_STD_450);
self.glsl = Some(id);
id
}
}
}
}
impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn gl_op(&mut self, op: GLOp, args: impl AsRef<[SpirvValue]>) -> SpirvValue {
let args = args.as_ref();
let glsl = self.ext_inst.borrow_mut().import_glsl(self);
self.emit()
.ext_inst(
args[0].ty,
None,
glsl,
op as u32,
args.iter().map(|a| Operand::IdRef(a.def)),
)
.unwrap()
.with_type(args[0].ty)
}
}

View File

@ -3,6 +3,7 @@ use crate::abi::ConvSpirvType;
use crate::builder_spirv::SpirvValueExt; use crate::builder_spirv::SpirvValueExt;
use crate::codegen_cx::CodegenCx; use crate::codegen_cx::CodegenCx;
use crate::spirv_type::SpirvType; use crate::spirv_type::SpirvType;
use rspirv::spirv::GLOp;
use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::common::IntPredicate;
use rustc_codegen_ssa::glue; use rustc_codegen_ssa::glue;
@ -455,6 +456,45 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
} }
} }
// TODO: Configure these to be ocl vs. gl ext instructions, etc.
sym::sqrtf32 | sym::sqrtf64 => self.gl_op(GLOp::Sqrt, [args[0].immediate()]),
sym::powif32 | sym::powif64 => {
let float = self.sitofp(args[1].immediate(), args[0].immediate().ty);
self.gl_op(GLOp::Pow, [args[0].immediate(), float])
}
sym::sinf32 | sym::sinf64 => self.gl_op(GLOp::Sin, [args[0].immediate()]),
sym::cosf32 | sym::cosf64 => self.gl_op(GLOp::Cos, [args[0].immediate()]),
sym::powf32 | sym::powf64 => {
self.gl_op(GLOp::Pow, [args[0].immediate(), args[1].immediate()])
}
sym::expf32 | sym::expf64 => self.gl_op(GLOp::Exp, [args[0].immediate()]),
sym::exp2f32 | sym::exp2f64 => self.gl_op(GLOp::Exp2, [args[0].immediate()]),
sym::logf32 | sym::logf64 => self.gl_op(GLOp::Log, [args[0].immediate()]),
sym::log2f32 | sym::log2f64 => self.gl_op(GLOp::Log2, [args[0].immediate()]),
sym::log10f32 | sym::log10f64 => {
// spir-v doesn't have log10, so,
// log10(x) == (1 / ln(10)) * ln(x)
let mul = self.constant_float(args[0].immediate().ty, 1.0 / 10.0f64.ln());
let ln = self.gl_op(GLOp::Log, [args[0].immediate()]);
self.mul(mul, ln)
}
sym::fmaf32 | sym::fmaf64 => self.gl_op(GLOp::Fma, [args[0].immediate()]),
sym::fabsf32 | sym::fabsf64 => self.gl_op(GLOp::FAbs, [args[0].immediate()]),
sym::minnumf32 | sym::minnumf64 => self.gl_op(GLOp::FMin, [args[0].immediate()]),
sym::maxnumf32 | sym::maxnumf64 => self.gl_op(GLOp::FMax, [args[0].immediate()]),
// sym::copysignf32 => "llvm.copysign.f32",
// sym::copysignf64 => "llvm.copysign.f64",
sym::floorf32 | sym::floorf64 => self.gl_op(GLOp::Floor, [args[0].immediate()]),
sym::ceilf32 | sym::ceilf64 => self.gl_op(GLOp::Ceil, [args[0].immediate()]),
sym::truncf32 | sym::truncf64 => self.gl_op(GLOp::Trunc, [args[0].immediate()]),
// TODO: Correctness of round
sym::rintf32
| sym::rintf64
| sym::nearbyintf32
| sym::nearbyintf64
| sym::roundf32
| sym::roundf64 => self.gl_op(GLOp::Round, [args[1].immediate()]),
sym::float_to_int_unchecked => { sym::float_to_int_unchecked => {
if float_type_width(arg_tys[0]).is_none() { if float_type_width(arg_tys[0]).is_none() {
span_invalid_monomorphization_error( span_invalid_monomorphization_error(

View File

@ -1,6 +1,9 @@
mod builder_methods; mod builder_methods;
mod ext_inst;
mod intrinsics; mod intrinsics;
pub use ext_inst::ExtInst;
use crate::abi::ConvSpirvType; use crate::abi::ConvSpirvType;
use crate::builder_spirv::{BuilderCursor, SpirvValue, SpirvValueExt}; use crate::builder_spirv::{BuilderCursor, SpirvValue, SpirvValueExt};
use crate::codegen_cx::CodegenCx; use crate::codegen_cx::CodegenCx;

View File

@ -1,4 +1,5 @@
use crate::abi::ConvSpirvType; use crate::abi::ConvSpirvType;
use crate::builder::ExtInst;
use crate::builder_spirv::{BuilderCursor, BuilderSpirv, SpirvValue, SpirvValueExt}; use crate::builder_spirv::{BuilderCursor, BuilderSpirv, SpirvValue, SpirvValueExt};
use crate::spirv_type::{SpirvType, SpirvTypePrinter, TypeCache}; use crate::spirv_type::{SpirvType, SpirvTypePrinter, TypeCache};
use rspirv::dr::{Module, Operand}; use rspirv::dr::{Module, Operand};
@ -63,6 +64,7 @@ pub struct CodegenCx<'tcx> {
pub type_cache: TypeCache<'tcx>, pub type_cache: TypeCache<'tcx>,
/// Cache generated vtables /// Cache generated vtables
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), SpirvValue>>, pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), SpirvValue>>,
pub ext_inst: RefCell<ExtInst>,
} }
impl<'tcx> CodegenCx<'tcx> { impl<'tcx> CodegenCx<'tcx> {
@ -76,6 +78,7 @@ impl<'tcx> CodegenCx<'tcx> {
function_parameter_values: RefCell::new(HashMap::new()), function_parameter_values: RefCell::new(HashMap::new()),
type_cache: Default::default(), type_cache: Default::default(),
vtables: RefCell::new(Default::default()), vtables: RefCell::new(Default::default()),
ext_inst: Default::default(),
} }
} }
@ -184,6 +187,14 @@ impl<'tcx> CodegenCx<'tcx> {
self.builder.constant_f64(ty, val).with_type(ty) self.builder.constant_f64(ty, val).with_type(ty)
} }
pub fn constant_float(&self, ty: Word, val: f64) -> SpirvValue {
match self.lookup_type(ty) {
SpirvType::Float(32) => self.builder.constant_f32(ty, val as f32).with_type(ty),
SpirvType::Float(64) => self.builder.constant_f64(ty, val).with_type(ty),
other => panic!("constant_float invalid on type {}", other.debug(ty, self)),
}
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn set_linkage_export(&self, target: Word, name: String) { pub fn set_linkage_export(&self, target: Word, name: String) {
self.emit_global().decorate( self.emit_global().decorate(