aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrzej Janik <[email protected]>2024-10-10 22:58:50 +0200
committerAndrzej Janik <[email protected]>2024-10-10 22:58:50 +0200
commitd7a435ff424316edc4e303f89a6373ac45ea1915 (patch)
tree082b484828360974184034d905b3ad89a59e40c5
parent6f2ca43cfa7033f4030cb964e7468fff13bb5da0 (diff)
downloadZLUDA-d7a435ff424316edc4e303f89a6373ac45ea1915.tar.gz
ZLUDA-d7a435ff424316edc4e303f89a6373ac45ea1915.zip
Readd most of the implicit conversion code
-rw-r--r--ptx/src/pass/emit_llvm.rs94
1 files changed, 69 insertions, 25 deletions
diff --git a/ptx/src/pass/emit_llvm.rs b/ptx/src/pass/emit_llvm.rs
index 2e9892f..c7e3bbb 100644
--- a/ptx/src/pass/emit_llvm.rs
+++ b/ptx/src/pass/emit_llvm.rs
@@ -577,31 +577,75 @@ impl<'a> MethodEmitContext<'a> {
let builder = self.builder;
match conversion.kind {
ConversionKind::Default => {
- let from_layout = conversion.from_type.layout();
- let to_layout = conversion.to_type.layout();
- if from_layout.size() == to_layout.size() {
- let src = self.resolver.value(conversion.src)?;
- let type_ = get_type(self.context, &conversion.to_type)?;
- self.resolver.with_result(conversion.dst, |dst| unsafe {
- LLVMBuildBitCast(builder, src, type_, dst)
- });
- Ok(())
- } else if to_layout.size() > from_layout.size() {
- // TODO: not entirely correct
- let src = self.resolver.value(conversion.src)?;
- let type_ = get_type(self.context, &conversion.to_type)?;
- self.resolver.with_result(conversion.dst, |dst| unsafe {
- LLVMBuildZExt(builder, src, type_, dst)
- });
- Ok(())
- } else {
- // TODO: not entirely correct
- let src = self.resolver.value(conversion.src)?;
- let type_ = get_type(self.context, &conversion.to_type)?;
- self.resolver.with_result(conversion.dst, |dst| unsafe {
- LLVMBuildTrunc(builder, src, type_, dst)
- });
- Ok(())
+ match (conversion.from_type, conversion.to_type) {
+ (ast::Type::Scalar(from_type), ast::Type::Scalar(to_type)) => {
+ let from_layout = conversion.from_type.layout();
+ let to_layout = conversion.to_type.layout();
+ if from_layout.size() == to_layout.size() {
+ let dst_type = get_type(self.context, &conversion.to_type)?;
+ if from_type.kind() != ast::ScalarKind::Float
+ && to_type.kind() != ast::ScalarKind::Float
+ {
+ // It is noop, but another instruction expects result of this conversion
+ self.resolver
+ .register(conversion.dst, self.resolver.value(conversion.src)?);
+ } else {
+ let src = self.resolver.value(conversion.src)?;
+ self.resolver.with_result(conversion.dst, |dst| unsafe {
+ LLVMBuildBitCast(builder, src, dst_type, dst)
+ });
+ }
+ Ok(())
+ } else {
+ let src = self.resolver.value(conversion.src)?;
+ // This block is safe because it's illegal to implictly convert between floating point values
+ let same_width_bit_type = unsafe {
+ LLVMIntTypeInContext(self.context, (from_layout.size() * 8) as u32)
+ };
+ let same_width_bit_value = unsafe {
+ LLVMBuildBitCast(
+ builder,
+ src,
+ same_width_bit_type,
+ LLVM_UNNAMED.as_ptr(),
+ )
+ };
+ let wide_bit_type = unsafe {
+ LLVMIntTypeInContext(self.context, (to_layout.size() * 8) as u32)
+ };
+ if to_type.kind() == ast::ScalarKind::Unsigned
+ || to_type.kind() == ast::ScalarKind::Bit
+ {
+ let llvm_fn = if to_type.size_of() >= from_type.size_of() {
+ LLVMBuildZExtOrBitCast
+ } else {
+ LLVMBuildTrunc
+ };
+ self.resolver.with_result(conversion.dst, |dst| unsafe {
+ llvm_fn(builder, same_width_bit_value, wide_bit_type, dst)
+ });
+ Ok(())
+ } else {
+ let conversion_fn = if from_type.kind() == ast::ScalarKind::Signed
+ && to_type.kind() == ast::ScalarKind::Signed
+ {
+ if to_type.size_of() >= from_type.size_of() {
+ LLVMBuildSExtOrBitCast
+ } else {
+ LLVMBuildTrunc
+ }
+ } else {
+ if to_type.size_of() >= from_type.size_of() {
+ LLVMBuildZExtOrBitCast
+ } else {
+ LLVMBuildTrunc
+ }
+ };
+ todo!()
+ }
+ }
+ }
+ _ => todo!(),
}
}
ConversionKind::SignExtend => todo!(),