|
1 | 1 | use std::borrow::Cow;
|
2 | 2 |
|
3 |
| -use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue}; |
| 3 | +use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type}; |
4 | 4 | use rustc_codegen_ssa::traits::BuilderMethods;
|
5 | 5 |
|
6 | 6 | use crate::builder::Builder;
|
7 | 7 | use crate::context::CodegenCx;
|
8 | 8 |
|
| 9 | +fn encode_key_128_type<'a, 'gcc, 'tcx>( |
| 10 | + builder: &Builder<'a, 'gcc, 'tcx>, |
| 11 | +) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) { |
| 12 | + let m128i = builder.context.new_vector_type(builder.i64_type, 2); |
| 13 | + let field1 = builder.context.new_field(None, builder.u32_type, "field1"); |
| 14 | + let field2 = builder.context.new_field(None, m128i, "field2"); |
| 15 | + let field3 = builder.context.new_field(None, m128i, "field3"); |
| 16 | + let field4 = builder.context.new_field(None, m128i, "field4"); |
| 17 | + let field5 = builder.context.new_field(None, m128i, "field5"); |
| 18 | + let field6 = builder.context.new_field(None, m128i, "field6"); |
| 19 | + let field7 = builder.context.new_field(None, m128i, "field7"); |
| 20 | + let encode_type = builder.context.new_struct_type( |
| 21 | + None, |
| 22 | + "EncodeKey128Output", |
| 23 | + &[field1, field2, field3, field4, field5, field6, field7], |
| 24 | + ); |
| 25 | + encode_type.as_type().set_packed(); |
| 26 | + (encode_type.as_type(), field1, field2) |
| 27 | +} |
| 28 | + |
| 29 | +fn encode_key_256_type<'a, 'gcc, 'tcx>( |
| 30 | + builder: &Builder<'a, 'gcc, 'tcx>, |
| 31 | +) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) { |
| 32 | + let m128i = builder.context.new_vector_type(builder.i64_type, 2); |
| 33 | + let field1 = builder.context.new_field(None, builder.u32_type, "field1"); |
| 34 | + let field2 = builder.context.new_field(None, m128i, "field2"); |
| 35 | + let field3 = builder.context.new_field(None, m128i, "field3"); |
| 36 | + let field4 = builder.context.new_field(None, m128i, "field4"); |
| 37 | + let field5 = builder.context.new_field(None, m128i, "field5"); |
| 38 | + let field6 = builder.context.new_field(None, m128i, "field6"); |
| 39 | + let field7 = builder.context.new_field(None, m128i, "field7"); |
| 40 | + let field8 = builder.context.new_field(None, m128i, "field8"); |
| 41 | + let encode_type = builder.context.new_struct_type( |
| 42 | + None, |
| 43 | + "EncodeKey256Output", |
| 44 | + &[field1, field2, field3, field4, field5, field6, field7, field8], |
| 45 | + ); |
| 46 | + encode_type.as_type().set_packed(); |
| 47 | + (encode_type.as_type(), field1, field2) |
| 48 | +} |
| 49 | + |
| 50 | +fn aes_output_type<'a, 'gcc, 'tcx>( |
| 51 | + builder: &Builder<'a, 'gcc, 'tcx>, |
| 52 | +) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) { |
| 53 | + let m128i = builder.context.new_vector_type(builder.i64_type, 2); |
| 54 | + let field1 = builder.context.new_field(None, builder.u8_type, "field1"); |
| 55 | + let field2 = builder.context.new_field(None, m128i, "field2"); |
| 56 | + let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]); |
| 57 | + let typ = aes_output_type.as_type(); |
| 58 | + typ.set_packed(); |
| 59 | + (typ, field1, field2) |
| 60 | +} |
| 61 | + |
| 62 | +fn wide_aes_output_type<'a, 'gcc, 'tcx>( |
| 63 | + builder: &Builder<'a, 'gcc, 'tcx>, |
| 64 | +) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) { |
| 65 | + let m128i = builder.context.new_vector_type(builder.i64_type, 2); |
| 66 | + let field1 = builder.context.new_field(None, builder.u8_type, "field1"); |
| 67 | + let field2 = builder.context.new_field(None, m128i, "field2"); |
| 68 | + let field3 = builder.context.new_field(None, m128i, "field3"); |
| 69 | + let field4 = builder.context.new_field(None, m128i, "field4"); |
| 70 | + let field5 = builder.context.new_field(None, m128i, "field5"); |
| 71 | + let field6 = builder.context.new_field(None, m128i, "field6"); |
| 72 | + let field7 = builder.context.new_field(None, m128i, "field7"); |
| 73 | + let field8 = builder.context.new_field(None, m128i, "field8"); |
| 74 | + let field9 = builder.context.new_field(None, m128i, "field9"); |
| 75 | + let aes_output_type = builder.context.new_struct_type( |
| 76 | + None, |
| 77 | + "WideAesOutput", |
| 78 | + &[field1, field2, field3, field4, field5, field6, field7, field8, field9], |
| 79 | + ); |
| 80 | + aes_output_type.as_type().set_packed(); |
| 81 | + (aes_output_type.as_type(), field1, field2) |
| 82 | +} |
| 83 | + |
9 | 84 | #[cfg_attr(not(feature = "master"), allow(unused_variables))]
|
10 | 85 | pub fn adjust_function<'gcc>(
|
11 | 86 | context: &'gcc Context<'gcc>,
|
@@ -503,6 +578,74 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
|
503 | 578 | let arg4 = builder.context.new_rvalue_from_int(arg4_type, -1);
|
504 | 579 | args = vec![a, b, c, arg4, new_args[3]].into();
|
505 | 580 | }
|
| 581 | + "__builtin_ia32_encodekey128_u32" => { |
| 582 | + let mut new_args = args.to_vec(); |
| 583 | + let m128i = builder.context.new_vector_type(builder.i64_type, 2); |
| 584 | + let array_type = builder.context.new_array_type(None, m128i, 6); |
| 585 | + let result = builder.current_func().new_local(None, array_type, "result"); |
| 586 | + new_args.push(result.get_address(None)); |
| 587 | + args = new_args.into(); |
| 588 | + } |
| 589 | + "__builtin_ia32_encodekey256_u32" => { |
| 590 | + let mut new_args = args.to_vec(); |
| 591 | + let m128i = builder.context.new_vector_type(builder.i64_type, 2); |
| 592 | + let array_type = builder.context.new_array_type(None, m128i, 7); |
| 593 | + let result = builder.current_func().new_local(None, array_type, "result"); |
| 594 | + new_args.push(result.get_address(None)); |
| 595 | + args = new_args.into(); |
| 596 | + } |
| 597 | + "__builtin_ia32_aesenc128kl_u8" |
| 598 | + | "__builtin_ia32_aesdec128kl_u8" |
| 599 | + | "__builtin_ia32_aesenc256kl_u8" |
| 600 | + | "__builtin_ia32_aesdec256kl_u8" => { |
| 601 | + let mut new_args = vec![]; |
| 602 | + // TODO: directly create a variable of type m128i instead of the whole struct? |
| 603 | + let (aes_output_type, _, field2) = aes_output_type(builder); |
| 604 | + let result = builder.current_func().new_local(None, aes_output_type, "result"); |
| 605 | + let field2 = result.access_field(None, field2); |
| 606 | + new_args.push(field2.get_address(None)); |
| 607 | + new_args.extend(args.to_vec()); |
| 608 | + args = new_args.into(); |
| 609 | + } |
| 610 | + "__builtin_ia32_aesencwide128kl_u8" |
| 611 | + | "__builtin_ia32_aesdecwide128kl_u8" |
| 612 | + | "__builtin_ia32_aesencwide256kl_u8" |
| 613 | + | "__builtin_ia32_aesdecwide256kl_u8" => { |
| 614 | + let mut new_args = vec![]; |
| 615 | + |
| 616 | + let mut old_args = args.to_vec(); |
| 617 | + let handle = old_args.swap_remove(0); // Called __P in GCC. |
| 618 | + let first_value = old_args.swap_remove(0); |
| 619 | + |
| 620 | + let element_type = first_value.get_type(); |
| 621 | + let array_type = builder.context.new_array_type(None, element_type, 8); |
| 622 | + let result = builder.current_func().new_local(None, array_type, "result"); |
| 623 | + new_args.push(result.get_address(None)); |
| 624 | + |
| 625 | + let array = builder.current_func().new_local(None, array_type, "array"); |
| 626 | + let input = builder.context.new_array_constructor( |
| 627 | + None, |
| 628 | + array_type, |
| 629 | + &[ |
| 630 | + first_value, |
| 631 | + old_args.swap_remove(0), |
| 632 | + old_args.swap_remove(0), |
| 633 | + old_args.swap_remove(0), |
| 634 | + old_args.swap_remove(0), |
| 635 | + old_args.swap_remove(0), |
| 636 | + old_args.swap_remove(0), |
| 637 | + old_args.swap_remove(0), |
| 638 | + ], |
| 639 | + ); |
| 640 | + builder.llbb().add_assignment(None, array, input); |
| 641 | + let input_ptr = array.get_address(None); |
| 642 | + let arg2_type = gcc_func.get_param_type(1); |
| 643 | + let input_ptr = builder.context.new_cast(None, input_ptr, arg2_type); |
| 644 | + new_args.push(input_ptr); |
| 645 | + |
| 646 | + new_args.push(handle); |
| 647 | + args = new_args.into(); |
| 648 | + } |
506 | 649 | _ => (),
|
507 | 650 | }
|
508 | 651 | } else {
|
@@ -700,6 +843,96 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
|
700 | 843 | let f16_type = builder.context.new_c_type(CType::Float16);
|
701 | 844 | return_value = builder.context.new_cast(None, return_value, f16_type);
|
702 | 845 | }
|
| 846 | + "__builtin_ia32_encodekey128_u32" => { |
| 847 | + // The builtin __builtin_ia32_encodekey128_u32 writes the result in its pointer argument while |
| 848 | + // llvm.x86.encodekey128 returns a value. |
| 849 | + // We added a result pointer argument and now need to assign its value to the return_value expected by |
| 850 | + // the LLVM intrinsic. |
| 851 | + let (encode_type, field1, field2) = encode_key_128_type(builder); |
| 852 | + let result = builder.current_func().new_local(None, encode_type, "result"); |
| 853 | + let field1 = result.access_field(None, field1); |
| 854 | + builder.llbb().add_assignment(None, field1, return_value); |
| 855 | + let field2 = result.access_field(None, field2); |
| 856 | + let field2_type = field2.to_rvalue().get_type(); |
| 857 | + let array_type = builder.context.new_array_type(None, field2_type, 6); |
| 858 | + let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer()); |
| 859 | + let field2_ptr = |
| 860 | + builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); |
| 861 | + builder.llbb().add_assignment( |
| 862 | + None, |
| 863 | + field2_ptr.dereference(None), |
| 864 | + ptr.dereference(None), |
| 865 | + ); |
| 866 | + return_value = result.to_rvalue(); |
| 867 | + } |
| 868 | + "__builtin_ia32_encodekey256_u32" => { |
| 869 | + // The builtin __builtin_ia32_encodekey256_u32 writes the result in its pointer argument while |
| 870 | + // llvm.x86.encodekey256 returns a value. |
| 871 | + // We added a result pointer argument and now need to assign its value to the return_value expected by |
| 872 | + // the LLVM intrinsic. |
| 873 | + let (encode_type, field1, field2) = encode_key_256_type(builder); |
| 874 | + let result = builder.current_func().new_local(None, encode_type, "result"); |
| 875 | + let field1 = result.access_field(None, field1); |
| 876 | + builder.llbb().add_assignment(None, field1, return_value); |
| 877 | + let field2 = result.access_field(None, field2); |
| 878 | + let field2_type = field2.to_rvalue().get_type(); |
| 879 | + let array_type = builder.context.new_array_type(None, field2_type, 7); |
| 880 | + let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer()); |
| 881 | + let field2_ptr = |
| 882 | + builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); |
| 883 | + builder.llbb().add_assignment( |
| 884 | + None, |
| 885 | + field2_ptr.dereference(None), |
| 886 | + ptr.dereference(None), |
| 887 | + ); |
| 888 | + return_value = result.to_rvalue(); |
| 889 | + } |
| 890 | + "__builtin_ia32_aesdec128kl_u8" |
| 891 | + | "__builtin_ia32_aesenc128kl_u8" |
| 892 | + | "__builtin_ia32_aesdec256kl_u8" |
| 893 | + | "__builtin_ia32_aesenc256kl_u8" => { |
| 894 | + // The builtin for aesdec/aesenc writes the result in its pointer argument while |
| 895 | + // llvm.x86.aesdec128kl returns a value. |
| 896 | + // We added a result pointer argument and now need to assign its value to the return_value expected by |
| 897 | + // the LLVM intrinsic. |
| 898 | + let (aes_output_type, field1, field2) = aes_output_type(builder); |
| 899 | + let result = builder.current_func().new_local(None, aes_output_type, "result"); |
| 900 | + let field1 = result.access_field(None, field1); |
| 901 | + builder.llbb().add_assignment(None, field1, return_value); |
| 902 | + let field2 = result.access_field(None, field2); |
| 903 | + let ptr = builder.context.new_cast( |
| 904 | + None, |
| 905 | + args[0], |
| 906 | + field2.to_rvalue().get_type().make_pointer(), |
| 907 | + ); |
| 908 | + builder.llbb().add_assignment(None, field2, ptr.dereference(None)); |
| 909 | + return_value = result.to_rvalue(); |
| 910 | + } |
| 911 | + "__builtin_ia32_aesencwide128kl_u8" |
| 912 | + | "__builtin_ia32_aesdecwide128kl_u8" |
| 913 | + | "__builtin_ia32_aesencwide256kl_u8" |
| 914 | + | "__builtin_ia32_aesdecwide256kl_u8" => { |
| 915 | + // The builtin for aesdecwide/aesencwide writes the result in its pointer argument while |
| 916 | + // llvm.x86.aesencwide128kl returns a value. |
| 917 | + // We added a result pointer argument and now need to assign its value to the return_value expected by |
| 918 | + // the LLVM intrinsic. |
| 919 | + let (aes_output_type, field1, field2) = wide_aes_output_type(builder); |
| 920 | + let result = builder.current_func().new_local(None, aes_output_type, "result"); |
| 921 | + let field1 = result.access_field(None, field1); |
| 922 | + builder.llbb().add_assignment(None, field1, return_value); |
| 923 | + let field2 = result.access_field(None, field2); |
| 924 | + let field2_type = field2.to_rvalue().get_type(); |
| 925 | + let array_type = builder.context.new_array_type(None, field2_type, 8); |
| 926 | + let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer()); |
| 927 | + let field2_ptr = |
| 928 | + builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); |
| 929 | + builder.llbb().add_assignment( |
| 930 | + None, |
| 931 | + field2_ptr.dereference(None), |
| 932 | + ptr.dereference(None), |
| 933 | + ); |
| 934 | + return_value = result.to_rvalue(); |
| 935 | + } |
703 | 936 | _ => (),
|
704 | 937 | }
|
705 | 938 |
|
@@ -1284,6 +1517,16 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
|
1284 | 1517 | "llvm.x86.avx512fp16.mask.vfmadd.cph.256" => "__builtin_ia32_vfmaddcph256_mask3",
|
1285 | 1518 | "llvm.x86.avx512fp16.mask.vfcmadd.cph.128" => "__builtin_ia32_vfcmaddcph128_mask3",
|
1286 | 1519 | "llvm.x86.avx512fp16.mask.vfmadd.cph.128" => "__builtin_ia32_vfmaddcph128_mask3",
|
| 1520 | + "llvm.x86.encodekey128" => "__builtin_ia32_encodekey128_u32", |
| 1521 | + "llvm.x86.encodekey256" => "__builtin_ia32_encodekey256_u32", |
| 1522 | + "llvm.x86.aesenc128kl" => "__builtin_ia32_aesenc128kl_u8", |
| 1523 | + "llvm.x86.aesdec128kl" => "__builtin_ia32_aesdec128kl_u8", |
| 1524 | + "llvm.x86.aesenc256kl" => "__builtin_ia32_aesenc256kl_u8", |
| 1525 | + "llvm.x86.aesdec256kl" => "__builtin_ia32_aesdec256kl_u8", |
| 1526 | + "llvm.x86.aesencwide128kl" => "__builtin_ia32_aesencwide128kl_u8", |
| 1527 | + "llvm.x86.aesdecwide128kl" => "__builtin_ia32_aesdecwide128kl_u8", |
| 1528 | + "llvm.x86.aesencwide256kl" => "__builtin_ia32_aesencwide256kl_u8", |
| 1529 | + "llvm.x86.aesdecwide256kl" => "__builtin_ia32_aesdecwide256kl_u8", |
1287 | 1530 |
|
1288 | 1531 | // TODO: support the tile builtins:
|
1289 | 1532 | "llvm.x86.ldtilecfg" => "__builtin_trap",
|
|
0 commit comments