|
3641 | 3641 | <a href="#3640" id="3640">3640</a> |
3642 | 3642 | <a href="#3641" id="3641">3641</a> |
3643 | 3643 | <a href="#3642" id="3642">3642</a> |
3644 | | -<a href="#3643" id="3643">3643</a></pre></div><pre class="rust"><code><span class="comment">// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). |
| 3644 | +<a href="#3643" id="3643">3643</a> |
| 3645 | +<a href="#3644" id="3644">3644</a> |
| 3646 | +<a href="#3645" id="3645">3645</a> |
| 3647 | +<a href="#3646" id="3646">3646</a> |
| 3648 | +<a href="#3647" id="3647">3647</a> |
| 3649 | +<a href="#3648" id="3648">3648</a> |
| 3650 | +<a href="#3649" id="3649">3649</a> |
| 3651 | +<a href="#3650" id="3650">3650</a> |
| 3652 | +<a href="#3651" id="3651">3651</a> |
| 3653 | +<a href="#3652" id="3652">3652</a> |
| 3654 | +<a href="#3653" id="3653">3653</a> |
| 3655 | +<a href="#3654" id="3654">3654</a> |
| 3656 | +<a href="#3655" id="3655">3655</a> |
| 3657 | +<a href="#3656" id="3656">3656</a> |
| 3658 | +<a href="#3657" id="3657">3657</a> |
| 3659 | +<a href="#3658" id="3658">3658</a> |
| 3660 | +<a href="#3659" id="3659">3659</a> |
| 3661 | +<a href="#3660" id="3660">3660</a> |
| 3662 | +<a href="#3661" id="3661">3661</a> |
| 3663 | +<a href="#3662" id="3662">3662</a> |
| 3664 | +<a href="#3663" id="3663">3663</a> |
| 3665 | +<a href="#3664" id="3664">3664</a> |
| 3666 | +<a href="#3665" id="3665">3665</a> |
| 3667 | +<a href="#3666" id="3666">3666</a> |
| 3668 | +<a href="#3667" id="3667">3667</a> |
| 3669 | +<a href="#3668" id="3668">3668</a> |
| 3670 | +<a href="#3669" id="3669">3669</a> |
| 3671 | +<a href="#3670" id="3670">3670</a> |
| 3672 | +<a href="#3671" id="3671">3671</a> |
| 3673 | +<a href="#3672" id="3672">3672</a> |
| 3674 | +<a href="#3673" id="3673">3673</a> |
| 3675 | +<a href="#3674" id="3674">3674</a> |
| 3676 | +<a href="#3675" id="3675">3675</a> |
| 3677 | +<a href="#3676" id="3676">3676</a> |
| 3678 | +<a href="#3677" id="3677">3677</a> |
| 3679 | +<a href="#3678" id="3678">3678</a> |
| 3680 | +<a href="#3679" id="3679">3679</a> |
| 3681 | +<a href="#3680" id="3680">3680</a> |
| 3682 | +<a href="#3681" id="3681">3681</a> |
| 3683 | +<a href="#3682" id="3682">3682</a> |
| 3684 | +<a href="#3683" id="3683">3683</a> |
| 3685 | +<a href="#3684" id="3684">3684</a> |
| 3686 | +<a href="#3685" id="3685">3685</a> |
| 3687 | +<a href="#3686" id="3686">3686</a> |
| 3688 | +<a href="#3687" id="3687">3687</a> |
| 3689 | +<a href="#3688" id="3688">3688</a> |
| 3690 | +<a href="#3689" id="3689">3689</a> |
| 3691 | +<a href="#3690" id="3690">3690</a> |
| 3692 | +<a href="#3691" id="3691">3691</a> |
| 3693 | +<a href="#3692" id="3692">3692</a> |
| 3694 | +<a href="#3693" id="3693">3693</a> |
| 3695 | +<a href="#3694" id="3694">3694</a> |
| 3696 | +<a href="#3695" id="3695">3695</a> |
| 3697 | +<a href="#3696" id="3696">3696</a> |
| 3698 | +<a href="#3697" id="3697">3697</a> |
| 3699 | +<a href="#3698" id="3698">3698</a> |
| 3700 | +<a href="#3699" id="3699">3699</a> |
| 3701 | +<a href="#3700" id="3700">3700</a> |
| 3702 | +<a href="#3701" id="3701">3701</a> |
| 3703 | +<a href="#3702" id="3702">3702</a> |
| 3704 | +<a href="#3703" id="3703">3703</a> |
| 3705 | +<a href="#3704" id="3704">3704</a> |
| 3706 | +<a href="#3705" id="3705">3705</a> |
| 3707 | +<a href="#3706" id="3706">3706</a> |
| 3708 | +<a href="#3707" id="3707">3707</a> |
| 3709 | +<a href="#3708" id="3708">3708</a> |
| 3710 | +<a href="#3709" id="3709">3709</a> |
| 3711 | +<a href="#3710" id="3710">3710</a> |
| 3712 | +<a href="#3711" id="3711">3711</a> |
| 3713 | +<a href="#3712" id="3712">3712</a> |
| 3714 | +<a href="#3713" id="3713">3713</a> |
| 3715 | +<a href="#3714" id="3714">3714</a> |
| 3716 | +<a href="#3715" id="3715">3715</a> |
| 3717 | +<a href="#3716" id="3716">3716</a> |
| 3718 | +<a href="#3717" id="3717">3717</a> |
| 3719 | +<a href="#3718" id="3718">3718</a> |
| 3720 | +<a href="#3719" id="3719">3719</a> |
| 3721 | +<a href="#3720" id="3720">3720</a> |
| 3722 | +<a href="#3721" id="3721">3721</a> |
| 3723 | +<a href="#3722" id="3722">3722</a> |
| 3724 | +<a href="#3723" id="3723">3723</a> |
| 3725 | +<a href="#3724" id="3724">3724</a> |
| 3726 | +<a href="#3725" id="3725">3725</a> |
| 3727 | +<a href="#3726" id="3726">3726</a> |
| 3728 | +<a href="#3727" id="3727">3727</a> |
| 3729 | +<a href="#3728" id="3728">3728</a> |
| 3730 | +<a href="#3729" id="3729">3729</a> |
| 3731 | +<a href="#3730" id="3730">3730</a> |
| 3732 | +<a href="#3731" id="3731">3731</a> |
| 3733 | +<a href="#3732" id="3732">3732</a> |
| 3734 | +<a href="#3733" id="3733">3733</a> |
| 3735 | +<a href="#3734" id="3734">3734</a> |
| 3736 | +<a href="#3735" id="3735">3735</a> |
| 3737 | +<a href="#3736" id="3736">3736</a> |
| 3738 | +<a href="#3737" id="3737">3737</a> |
| 3739 | +<a href="#3738" id="3738">3738</a> |
| 3740 | +<a href="#3739" id="3739">3739</a> |
| 3741 | +<a href="#3740" id="3740">3740</a> |
| 3742 | +<a href="#3741" id="3741">3741</a> |
| 3743 | +<a href="#3742" id="3742">3742</a> |
| 3744 | +<a href="#3743" id="3743">3743</a> |
| 3745 | +<a href="#3744" id="3744">3744</a> |
| 3746 | +<a href="#3745" id="3745">3745</a> |
| 3747 | +<a href="#3746" id="3746">3746</a> |
| 3748 | +<a href="#3747" id="3747">3747</a></pre></div><pre class="rust"><code><span class="comment">// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). |
3645 | 3749 | </span><span class="kw">use </span><span class="kw">crate</span>::maybe_pqp_cg_ssa <span class="kw">as </span>rustc_codegen_ssa; |
3646 | 3750 |
|
3647 | 3751 | <span class="kw">use </span><span class="kw">super</span>::Builder; |
|
5676 | 5780 | <span class="kw">if </span>val.ty == dest_ty { |
5677 | 5781 | val |
5678 | 5782 | } <span class="kw">else </span>{ |
5679 | | - <span class="self">self</span>.emit() |
| 5783 | + <span class="comment">// If casting a constant, directly create a constant of the target type. |
| 5784 | + // This avoids creating intermediate types that might require additional |
| 5785 | + // capabilities. For example, casting a f16 constant to f32 will directly |
| 5786 | + // create a f32 constant, avoiding the need for Float16 capability if it is |
| 5787 | + // not used elsewhere. |
| 5788 | + </span><span class="kw">if let </span><span class="prelude-val">Some</span>(const_val) = <span class="self">self</span>.builder.lookup_const_scalar(val) { |
| 5789 | + <span class="kw">if let </span>(SpirvType::Float(src_width), SpirvType::Float(dst_width)) = |
| 5790 | + (<span class="self">self</span>.lookup_type(val.ty), <span class="self">self</span>.lookup_type(dest_ty)) |
| 5791 | + { |
| 5792 | + <span class="kw">if </span>src_width < dst_width { |
| 5793 | + <span class="comment">// Convert the bit representation to the actual float value |
| 5794 | + </span><span class="kw">let </span>float_val = <span class="kw">match </span>src_width { |
| 5795 | + <span class="number">32 </span>=> <span class="prelude-val">Some</span>(f32::from_bits(const_val <span class="kw">as </span>u32) <span class="kw">as </span>f64), |
| 5796 | + <span class="number">64 </span>=> <span class="prelude-val">Some</span>(f64::from_bits(const_val <span class="kw">as </span>u64)), |
| 5797 | + <span class="kw">_ </span>=> <span class="prelude-val">None</span>, |
| 5798 | + }; |
| 5799 | + |
| 5800 | + <span class="kw">if let </span><span class="prelude-val">Some</span>(val) = float_val { |
| 5801 | + <span class="kw">return </span><span class="self">self</span>.constant_float(dest_ty, val); |
| 5802 | + } |
| 5803 | + } |
| 5804 | + } |
| 5805 | + } |
| 5806 | + |
| 5807 | + <span class="comment">// Regular conversion |
| 5808 | + </span><span class="self">self</span>.emit() |
5680 | 5809 | .f_convert(dest_ty, <span class="prelude-val">None</span>, val.def(<span class="self">self</span>)) |
5681 | 5810 | .unwrap() |
5682 | 5811 | .with_type(dest_ty) |
|
5841 | 5970 | <span class="comment">// I guess? |
5842 | 5971 | </span><span class="kw">return </span>val; |
5843 | 5972 | } |
| 5973 | + |
| 5974 | + <span class="comment">// If casting a constant, directly create a constant of the target type. This |
| 5975 | + // avoids creating intermediate types that might require additional |
| 5976 | + // capabilities. For example, casting a u8 constant to u32 will directly create |
| 5977 | + // a u32 constant, avoiding the need for Int8 capability if it is not used |
| 5978 | + // elsewhere. |
| 5979 | + </span><span class="kw">if let </span><span class="prelude-val">Some</span>(const_val) = <span class="self">self</span>.builder.lookup_const_scalar(val) { |
| 5980 | + <span class="kw">let </span>src_ty = <span class="self">self</span>.lookup_type(val.ty); |
| 5981 | + <span class="kw">let </span>dst_ty_spv = <span class="self">self</span>.lookup_type(dest_ty); |
| 5982 | + |
| 5983 | + <span class="comment">// Try to optimize the constant cast |
| 5984 | + </span><span class="kw">let </span>optimized_result = <span class="kw">match </span>(src_ty, dst_ty_spv) { |
| 5985 | + <span class="comment">// Integer to integer cast |
| 5986 | + </span>(SpirvType::Integer(src_width, <span class="kw">_</span>), SpirvType::Integer(dst_width, <span class="kw">_</span>)) => { |
| 5987 | + <span class="comment">// Only optimize if we're widening. This avoids creating the source |
| 5988 | + // type when it's safe to do so. For narrowing casts (e.g., u32 as |
| 5989 | + // u8), we need the proper truncation behavior that the regular cast |
| 5990 | + // provides. |
| 5991 | + </span><span class="kw">if </span>src_width < dst_width { |
| 5992 | + <span class="prelude-val">Some</span>(<span class="self">self</span>.constant_int(dest_ty, const_val)) |
| 5993 | + } <span class="kw">else </span>{ |
| 5994 | + <span class="prelude-val">None |
| 5995 | + </span>} |
| 5996 | + } |
| 5997 | + <span class="comment">// Bool to integer cast - const_val will be 0 or 1 |
| 5998 | + </span>(SpirvType::Bool, SpirvType::Integer(<span class="kw">_</span>, <span class="kw">_</span>)) => { |
| 5999 | + <span class="prelude-val">Some</span>(<span class="self">self</span>.constant_int(dest_ty, const_val)) |
| 6000 | + } |
| 6001 | + <span class="comment">// Integer to bool cast - compare with zero |
| 6002 | + </span>(SpirvType::Integer(<span class="kw">_</span>, <span class="kw">_</span>), SpirvType::Bool) => { |
| 6003 | + <span class="prelude-val">Some</span>(<span class="self">self</span>.constant_bool(<span class="self">self</span>.span(), const_val != <span class="number">0</span>)) |
| 6004 | + } |
| 6005 | + <span class="kw">_ </span>=> <span class="prelude-val">None</span>, |
| 6006 | + }; |
| 6007 | + |
| 6008 | + <span class="kw">if let </span><span class="prelude-val">Some</span>(result) = optimized_result { |
| 6009 | + <span class="kw">return </span>result; |
| 6010 | + } |
| 6011 | + } |
| 6012 | + |
5844 | 6013 | <span class="kw">match </span>(<span class="self">self</span>.lookup_type(val.ty), <span class="self">self</span>.lookup_type(dest_ty)) { |
5845 | 6014 | <span class="comment">// sign change |
5846 | 6015 | </span>( |
|
6771 | 6940 | .and_then(|def_id| <span class="self">self</span>.buffer_store_intrinsics.borrow().get(<span class="kw-2">&</span>def_id).copied()); |
6772 | 6941 | <span class="kw">let </span>is_panic_entry_point = instance_def_id |
6773 | 6942 | .is_some_and(|def_id| <span class="self">self</span>.panic_entry_points.borrow().contains(<span class="kw-2">&</span>def_id)); |
| 6943 | + <span class="kw">let </span>from_trait_impl = |
| 6944 | + instance_def_id.and_then(|def_id| <span class="self">self</span>.from_trait_impls.borrow().get(<span class="kw-2">&</span>def_id).copied()); |
6774 | 6945 |
|
6775 | 6946 | <span class="kw">if let </span><span class="prelude-val">Some</span>(libm_intrinsic) = libm_intrinsic { |
6776 | 6947 | <span class="kw">let </span>result = <span class="self">self</span>.call_libm_intrinsic(libm_intrinsic, result_type, args); |
|
6782 | 6953 | <span class="self">self</span>.debug_type(result.ty), |
6783 | 6954 | ); |
6784 | 6955 | } |
6785 | | - result |
6786 | | - } <span class="kw">else if </span>is_panic_entry_point { |
| 6956 | + <span class="kw">return </span>result; |
| 6957 | + } |
| 6958 | + |
| 6959 | + <span class="kw">if </span>is_panic_entry_point { |
6787 | 6960 | <span class="comment">// HACK(eddyb) Rust 2021 `panic!` always uses `format_args!`, even |
6788 | 6961 | // in the simple case that used to pass a `&str` constant, which |
6789 | 6962 | // would not remain reachable in the SPIR-V - but `format_args!` is |
|
7256 | 7429 | <span class="comment">// HACK(eddyb) redirect any possible panic call to an abort, to avoid |
7257 | 7430 | // needing to materialize `&core::panic::Location` or `format_args!`. |
7258 | 7431 | </span><span class="self">self</span>.abort_with_kind_and_message_debug_printf(<span class="string">"panic"</span>, message, debug_printf_args); |
7259 | | - <span class="self">self</span>.undef(result_type) |
7260 | | - } <span class="kw">else if let </span><span class="prelude-val">Some</span>(mode) = buffer_load_intrinsic { |
7261 | | - <span class="self">self</span>.codegen_buffer_load_intrinsic(result_type, args, mode) |
7262 | | - } <span class="kw">else if let </span><span class="prelude-val">Some</span>(mode) = buffer_store_intrinsic { |
| 7432 | + <span class="kw">return </span><span class="self">self</span>.undef(result_type); |
| 7433 | + } |
| 7434 | + |
| 7435 | + <span class="kw">if let </span><span class="prelude-val">Some</span>(mode) = buffer_load_intrinsic { |
| 7436 | + <span class="kw">return </span><span class="self">self</span>.codegen_buffer_load_intrinsic(result_type, args, mode); |
| 7437 | + } |
| 7438 | + |
| 7439 | + <span class="kw">if let </span><span class="prelude-val">Some</span>(mode) = buffer_store_intrinsic { |
7263 | 7440 | <span class="self">self</span>.codegen_buffer_store_intrinsic(args, mode); |
7264 | 7441 |
|
7265 | 7442 | <span class="kw">let </span>void_ty = SpirvType::Void.def(rustc_span::DUMMY_SP, <span class="self">self</span>); |
7266 | | - SpirvValue { |
| 7443 | + <span class="kw">return </span>SpirvValue { |
7267 | 7444 | kind: SpirvValueKind::IllegalTypeUsed(void_ty), |
7268 | 7445 | ty: void_ty, |
| 7446 | + }; |
| 7447 | + } |
| 7448 | + |
| 7449 | + <span class="kw">if let </span><span class="prelude-val">Some</span>((source_ty, target_ty)) = from_trait_impl { |
| 7450 | + <span class="comment">// Optimize From::from calls with constant arguments to avoid creating intermediate types. |
| 7451 | + // Since From is only implemented for safe conversions (widening conversions that preserve |
| 7452 | + // the numeric value), we can directly create a constant of the target type for primitive |
| 7453 | + // numeric types. |
| 7454 | + </span><span class="kw">if let </span>[arg] = args { |
| 7455 | + <span class="kw">if let </span><span class="prelude-val">Some</span>(const_val) = <span class="self">self</span>.builder.lookup_const_scalar(<span class="kw-2">*</span>arg) { |
| 7456 | + <span class="kw">use </span>rustc_middle::ty::FloatTy; |
| 7457 | + <span class="kw">let </span>optimized_result = <span class="kw">match </span>(source_ty.kind(), target_ty.kind()) { |
| 7458 | + <span class="comment">// Integer widening conversions |
| 7459 | + </span>(ty::Uint(<span class="kw">_</span>), ty::Uint(<span class="kw">_</span>)) | (ty::Int(<span class="kw">_</span>), ty::Int(<span class="kw">_</span>)) => { |
| 7460 | + <span class="prelude-val">Some</span>(<span class="self">self</span>.constant_int(result_type, const_val)) |
| 7461 | + } |
| 7462 | + <span class="comment">// Float widening conversions |
| 7463 | + // TODO(@LegNeato): Handle more float types |
| 7464 | + </span>(ty::Float(FloatTy::F32), ty::Float(FloatTy::F64)) => { |
| 7465 | + <span class="kw">let </span>float_val = f32::from_bits(const_val <span class="kw">as </span>u32) <span class="kw">as </span>f64; |
| 7466 | + <span class="prelude-val">Some</span>(<span class="self">self</span>.constant_float(result_type, float_val)) |
| 7467 | + } |
| 7468 | + <span class="comment">// No optimization for narrowing conversions or unsupported types |
| 7469 | + </span><span class="kw">_ </span>=> <span class="prelude-val">None</span>, |
| 7470 | + }; |
| 7471 | + |
| 7472 | + <span class="kw">if let </span><span class="prelude-val">Some</span>(result) = optimized_result { |
| 7473 | + <span class="kw">return </span>result; |
| 7474 | + } |
| 7475 | + } |
7269 | 7476 | } |
7270 | | - } <span class="kw">else </span>{ |
7271 | | - <span class="kw">let </span>args = args.iter().map(|arg| arg.def(<span class="self">self</span>)).collect::<Vec<<span class="kw">_</span>>>(); |
7272 | | - <span class="self">self</span>.emit() |
7273 | | - .function_call(result_type, <span class="prelude-val">None</span>, callee_val, args) |
7274 | | - .unwrap() |
7275 | | - .with_type(result_type) |
7276 | 7477 | } |
| 7478 | + |
| 7479 | + <span class="comment">// Default: emit a regular function call |
| 7480 | + </span><span class="kw">let </span>args = args.iter().map(|arg| arg.def(<span class="self">self</span>)).collect::<Vec<<span class="kw">_</span>>>(); |
| 7481 | + <span class="self">self</span>.emit() |
| 7482 | + .function_call(result_type, <span class="prelude-val">None</span>, callee_val, args) |
| 7483 | + .unwrap() |
| 7484 | + .with_type(result_type) |
7277 | 7485 | } |
7278 | 7486 |
|
7279 | 7487 | <span class="kw">fn </span>zext(<span class="kw-2">&mut </span><span class="self">self</span>, val: <span class="self">Self</span>::Value, dest_ty: <span class="self">Self</span>::Type) -> <span class="self">Self</span>::Value { |
|
0 commit comments