mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-08-02 14:57:43 +03:00
Fix integer shifts
This commit is contained in:
@ -2063,45 +2063,50 @@ impl<'a> MethodEmitContext<'a> {
|
|||||||
*const i8,
|
*const i8,
|
||||||
) -> LLVMValueRef,
|
) -> LLVMValueRef,
|
||||||
) -> Result<(), TranslateError> {
|
) -> Result<(), TranslateError> {
|
||||||
|
let llvm_type = get_scalar_type(self.context, type_);
|
||||||
let src1 = self.resolver.value(src1)?;
|
let src1 = self.resolver.value(src1)?;
|
||||||
let shift_size = self.resolver.value(src2)?;
|
let shift_size = self.resolver.value(src2)?;
|
||||||
let integer_bits = type_.layout().size() * 8;
|
let typed_shift_size = if type_.layout().size() >= 4 {
|
||||||
let integer_bits_constant = unsafe {
|
|
||||||
LLVMConstInt(
|
|
||||||
get_scalar_type(self.context, ast::ScalarType::U32),
|
|
||||||
integer_bits as u64,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let should_clamp = unsafe {
|
|
||||||
LLVMBuildICmp(
|
|
||||||
self.builder,
|
|
||||||
LLVMIntPredicate::LLVMIntUGE,
|
|
||||||
shift_size,
|
|
||||||
integer_bits_constant,
|
|
||||||
LLVM_UNNAMED.as_ptr(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let llvm_type = get_scalar_type(self.context, type_);
|
|
||||||
let zero = unsafe { LLVMConstNull(llvm_type) };
|
|
||||||
let normalized_shift_size = if type_.layout().size() >= 4 {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
LLVMBuildZExtOrBitCast(self.builder, shift_size, llvm_type, LLVM_UNNAMED.as_ptr())
|
LLVMBuildZExtOrBitCast(self.builder, shift_size, llvm_type, LLVM_UNNAMED.as_ptr())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsafe { LLVMBuildTrunc(self.builder, shift_size, llvm_type, LLVM_UNNAMED.as_ptr()) }
|
unsafe { LLVMBuildTrunc(self.builder, shift_size, llvm_type, LLVM_UNNAMED.as_ptr()) }
|
||||||
};
|
};
|
||||||
let shifted = unsafe {
|
let integer_bits = type_.layout().size() * 8;
|
||||||
llvm_fn(
|
let integer_bits_constant = unsafe { LLVMConstInt(llvm_type, integer_bits as u64, 0) };
|
||||||
|
let should_clamp = unsafe {
|
||||||
|
LLVMBuildICmp(
|
||||||
self.builder,
|
self.builder,
|
||||||
src1,
|
LLVMIntPredicate::LLVMIntUGE,
|
||||||
normalized_shift_size,
|
typed_shift_size,
|
||||||
|
integer_bits_constant,
|
||||||
LLVM_UNNAMED.as_ptr(),
|
LLVM_UNNAMED.as_ptr(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.resolver.with_result(dst, |dst| unsafe {
|
if type_.kind() == ast::ScalarKind::Signed {
|
||||||
LLVMBuildSelect(self.builder, should_clamp, zero, shifted, dst)
|
let integer_bits_constant_minus_one =
|
||||||
});
|
unsafe { LLVMConstInt(llvm_type, integer_bits as u64 - 1, 0) };
|
||||||
|
let clamped_shift_size = unsafe {
|
||||||
|
LLVMBuildSelect(
|
||||||
|
self.builder,
|
||||||
|
should_clamp,
|
||||||
|
integer_bits_constant_minus_one,
|
||||||
|
typed_shift_size,
|
||||||
|
LLVM_UNNAMED.as_ptr(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
self.resolver.with_result(dst, |dst| unsafe {
|
||||||
|
llvm_fn(self.builder, src1, clamped_shift_size, dst)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let shifted_value =
|
||||||
|
unsafe { llvm_fn(self.builder, src1, typed_shift_size, LLVM_UNNAMED.as_ptr()) };
|
||||||
|
let zero = unsafe { LLVMConstNull(llvm_type) };
|
||||||
|
self.resolver.with_result(dst, |dst| unsafe {
|
||||||
|
LLVMBuildSelect(self.builder, should_clamp, zero, shifted_value, dst)
|
||||||
|
});
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user