1use crate::{
4 ir::{
5 attribute::{
6 DenseI32ArrayAttribute, DenseI64ArrayAttribute, IntegerAttribute, StringAttribute,
7 TypeAttribute,
8 },
9 operation::OperationBuilder,
10 r#type::IntegerType,
11 Attribute, Identifier, Location, Operation, Region, Type, Value,
12 },
13 Context,
14};
15pub use alloca_options::*;
16pub use load_store_options::*;
17
18mod alloca_options;
19pub mod attributes;
20mod load_store_options;
21pub mod r#type;
22
23pub fn extract_value<'c>(
27 context: &'c Context,
28 container: Value<'c, '_>,
29 position: DenseI64ArrayAttribute<'c>,
30 result_type: Type<'c>,
31 location: Location<'c>,
32) -> Operation<'c> {
33 OperationBuilder::new("llvm.extractvalue", location)
34 .add_attributes(&[(Identifier::new(context, "position"), position.into())])
35 .add_operands(&[container])
36 .add_results(&[result_type])
37 .build()
38 .expect("valid operation")
39}
40
41pub fn get_element_ptr<'c>(
43 context: &'c Context,
44 ptr: Value<'c, '_>,
45 indices: DenseI32ArrayAttribute<'c>,
46 element_type: Type<'c>,
47 result_type: Type<'c>,
48 location: Location<'c>,
49) -> Operation<'c> {
50 OperationBuilder::new("llvm.getelementptr", location)
51 .add_attributes(&[
52 (
53 Identifier::new(context, "rawConstantIndices"),
54 indices.into(),
55 ),
56 (
57 Identifier::new(context, "elem_type"),
58 TypeAttribute::new(element_type).into(),
59 ),
60 ])
61 .add_operands(&[ptr])
62 .add_results(&[result_type])
63 .build()
64 .expect("valid operation")
65}
66
67pub fn get_element_ptr_dynamic<'c, const N: usize>(
69 context: &'c Context,
70 ptr: Value<'c, '_>,
71 indices: &[Value<'c, '_>; N],
72 element_type: Type<'c>,
73 result_type: Type<'c>,
74 location: Location<'c>,
75) -> Operation<'c> {
76 OperationBuilder::new("llvm.getelementptr", location)
77 .add_attributes(&[
78 (
79 Identifier::new(context, "rawConstantIndices"),
80 DenseI32ArrayAttribute::new(context, &[i32::MIN; N]).into(),
81 ),
82 (
83 Identifier::new(context, "elem_type"),
84 TypeAttribute::new(element_type).into(),
85 ),
86 ])
87 .add_operands(&[ptr])
88 .add_operands(indices)
89 .add_results(&[result_type])
90 .build()
91 .expect("valid operation")
92}
93
94pub fn insert_value<'c>(
96 context: &'c Context,
97 container: Value<'c, '_>,
98 position: DenseI64ArrayAttribute<'c>,
99 value: Value<'c, '_>,
100 location: Location<'c>,
101) -> Operation<'c> {
102 OperationBuilder::new("llvm.insertvalue", location)
103 .add_attributes(&[(Identifier::new(context, "position"), position.into())])
104 .add_operands(&[container, value])
105 .enable_result_type_inference()
106 .build()
107 .expect("valid operation")
108}
109
110pub fn undef<'c>(result_type: Type<'c>, location: Location<'c>) -> Operation<'c> {
112 OperationBuilder::new("llvm.mlir.undef", location)
113 .add_results(&[result_type])
114 .build()
115 .expect("valid operation")
116}
117
118pub fn poison<'c>(result_type: Type<'c>, location: Location<'c>) -> Operation<'c> {
120 OperationBuilder::new("llvm.mlir.poison", location)
121 .add_results(&[result_type])
122 .build()
123 .expect("valid operation")
124}
125
126pub fn zero<'c>(r#type: Type<'c>, location: Location<'c>) -> Operation<'c> {
128 OperationBuilder::new("llvm.mlir.zero", location)
129 .add_results(&[r#type])
130 .build()
131 .expect("valid operation")
132}
133
134#[deprecated]
136pub fn nullptr<'c>(ptr_type: Type<'c>, location: Location<'c>) -> Operation<'c> {
137 zero(ptr_type, location)
138}
139
140pub fn unreachable(location: Location) -> Operation {
142 OperationBuilder::new("llvm.unreachable", location)
143 .build()
144 .expect("valid operation")
145}
146
147pub fn bitcast<'c>(
149 argument: Value<'c, '_>,
150 result: Type<'c>,
151 location: Location<'c>,
152) -> Operation<'c> {
153 OperationBuilder::new("llvm.bitcast", location)
154 .add_operands(&[argument])
155 .add_results(&[result])
156 .build()
157 .expect("valid operation")
158}
159
160pub fn alloca<'c>(
162 context: &'c Context,
163 array_size: Value<'c, '_>,
164 ptr_type: Type<'c>,
165 location: Location<'c>,
166 extra_options: AllocaOptions<'c>,
167) -> Operation<'c> {
168 OperationBuilder::new("llvm.alloca", location)
169 .add_operands(&[array_size])
170 .add_attributes(&extra_options.into_attributes(context))
171 .add_results(&[ptr_type])
172 .build()
173 .expect("valid operation")
174}
175
176pub fn store<'c>(
178 context: &'c Context,
179 value: Value<'c, '_>,
180 addr: Value<'c, '_>,
181 location: Location<'c>,
182 extra_options: LoadStoreOptions<'c>,
183) -> Operation<'c> {
184 OperationBuilder::new("llvm.store", location)
185 .add_operands(&[value, addr])
186 .add_attributes(&extra_options.into_attributes(context))
187 .build()
188 .expect("valid operation")
189}
190
191pub fn load<'c>(
193 context: &'c Context,
194 addr: Value<'c, '_>,
195 r#type: Type<'c>,
196 location: Location<'c>,
197 extra_options: LoadStoreOptions<'c>,
198) -> Operation<'c> {
199 OperationBuilder::new("llvm.load", location)
200 .add_operands(&[addr])
201 .add_attributes(&extra_options.into_attributes(context))
202 .add_results(&[r#type])
203 .build()
204 .expect("valid operation")
205}
206
207pub fn func<'c>(
209 context: &'c Context,
210 name: StringAttribute<'c>,
211 r#type: TypeAttribute<'c>,
212 region: Region<'c>,
213 attributes: &[(Identifier<'c>, Attribute<'c>)],
214 location: Location<'c>,
215) -> Operation<'c> {
216 OperationBuilder::new("llvm.func", location)
217 .add_attributes(&[
218 (Identifier::new(context, "sym_name"), name.into()),
219 (Identifier::new(context, "function_type"), r#type.into()),
220 ])
221 .add_attributes(attributes)
222 .add_regions([region])
223 .build()
224 .expect("valid operation")
225}
226
227pub fn r#return<'c>(value: Option<Value<'c, '_>>, location: Location<'c>) -> Operation<'c> {
229 let mut builder = OperationBuilder::new("llvm.return", location);
230
231 if let Some(value) = value {
232 builder = builder.add_operands(&[value]);
233 }
234
235 builder.build().expect("valid operation")
236}
237
238pub fn call_intrinsic<'c>(
240 context: &'c Context,
241 intrin: StringAttribute<'c>,
242 args: &[Value<'c, '_>],
243 results: &[Type<'c>],
244 location: Location<'c>,
245) -> Operation<'c> {
246 OperationBuilder::new("llvm.call_intrinsic", location)
247 .add_operands(args)
248 .add_attributes(&[(Identifier::new(context, "intrin"), intrin.into())])
249 .add_results(results)
250 .build()
251 .expect("valid operation")
252}
253
254pub fn intr_ctlz<'c>(
256 context: &'c Context,
257 value: Value<'c, '_>,
258 is_zero_poison: bool,
259 result_type: Type<'c>,
260 location: Location<'c>,
261) -> Operation<'c> {
262 OperationBuilder::new("llvm.intr.ctlz", location)
263 .add_attributes(&[(
264 Identifier::new(context, "is_zero_poison"),
265 IntegerAttribute::new(IntegerType::new(context, 1).into(), is_zero_poison.into())
266 .into(),
267 )])
268 .add_operands(&[value])
269 .add_results(&[result_type])
270 .build()
271 .expect("valid operation")
272}
273
274pub fn intr_cttz<'c>(
276 context: &'c Context,
277 value: Value<'c, '_>,
278 is_zero_poison: bool,
279 result_type: Type<'c>,
280 location: Location<'c>,
281) -> Operation<'c> {
282 OperationBuilder::new("llvm.intr.cttz", location)
283 .add_attributes(&[(
284 Identifier::new(context, "is_zero_poison"),
285 IntegerAttribute::new(IntegerType::new(context, 1).into(), is_zero_poison.into())
286 .into(),
287 )])
288 .add_operands(&[value])
289 .add_results(&[result_type])
290 .build()
291 .expect("valid operation")
292}
293
294pub fn intr_ctpop<'c>(
296 value: Value<'c, '_>,
297 result_type: Type<'c>,
298 location: Location<'c>,
299) -> Operation<'c> {
300 OperationBuilder::new("llvm.intr.ctpop", location)
301 .add_operands(&[value])
302 .add_results(&[result_type])
303 .build()
304 .expect("valid operation")
305}
306
307pub fn intr_bswap<'c>(
309 value: Value<'c, '_>,
310 result_type: Type<'c>,
311 location: Location<'c>,
312) -> Operation<'c> {
313 OperationBuilder::new("llvm.intr.bswap", location)
314 .add_operands(&[value])
315 .add_results(&[result_type])
316 .build()
317 .expect("valid operation")
318}
319
320pub fn intr_bitreverse<'c>(
322 value: Value<'c, '_>,
323 result_type: Type<'c>,
324 location: Location<'c>,
325) -> Operation<'c> {
326 OperationBuilder::new("llvm.intr.bitreverse", location)
327 .add_operands(&[value])
328 .add_results(&[result_type])
329 .build()
330 .expect("valid operation")
331}
332
333pub fn intr_abs<'c>(
335 context: &'c Context,
336 value: Value<'c, '_>,
337 is_int_min_poison: bool,
338 result_type: Type<'c>,
339 location: Location<'c>,
340) -> Operation<'c> {
341 OperationBuilder::new("llvm.intr.abs", location)
342 .add_attributes(&[(
343 Identifier::new(context, "is_int_min_poison"),
344 IntegerAttribute::new(
345 IntegerType::new(context, 1).into(),
346 is_int_min_poison.into(),
347 )
348 .into(),
349 )])
350 .add_operands(&[value])
351 .add_results(&[result_type])
352 .build()
353 .expect("valid operation")
354}
355
356pub fn zext<'c>(
358 value: Value<'c, '_>,
359 result_type: Type<'c>,
360 location: Location<'c>,
361) -> Operation<'c> {
362 OperationBuilder::new("llvm.zext", location)
363 .add_operands(&[value])
364 .add_results(&[result_type])
365 .build()
366 .expect("valid operation")
367}
368
369#[cfg(test)]
370mod tests {
371 use tests::r#type::pointer;
372
373 use super::*;
374 use crate::{
375 dialect::{
376 arith, func,
377 llvm::{
378 attributes::{linkage, Linkage},
379 r#type::function,
380 },
381 },
382 ir::{
383 attribute::{IntegerAttribute, StringAttribute, TypeAttribute},
384 r#type::{FunctionType, IntegerType},
385 Block, Module, Region,
386 },
387 pass::{self, PassManager},
388 test::create_test_context,
389 };
390
391 fn convert_module<'c>(context: &'c Context, module: &mut Module<'c>) {
392 let pass_manager = PassManager::new(context);
393
394 pass_manager.add_pass(pass::conversion::create_func_to_llvm());
395 pass_manager
396 .nested_under("func.func")
397 .add_pass(pass::conversion::create_arith_to_llvm());
398 pass_manager
399 .nested_under("func.func")
400 .add_pass(pass::conversion::create_index_to_llvm());
401 pass_manager.add_pass(pass::conversion::create_scf_to_control_flow());
402 pass_manager.add_pass(pass::conversion::create_control_flow_to_llvm());
403 pass_manager.add_pass(pass::conversion::create_finalize_mem_ref_to_llvm());
404
405 assert_eq!(pass_manager.run(module), Ok(()));
406 assert!(module.as_operation().verify());
407 }
408
409 #[test]
410 fn compile_extract_value() {
411 let context = create_test_context();
412
413 let location = Location::unknown(&context);
414 let mut module = Module::new(location);
415 let integer_type = IntegerType::new(&context, 64).into();
416 let struct_type = r#type::r#struct(&context, &[integer_type], false);
417
418 module.body().append_operation(func::func(
419 &context,
420 StringAttribute::new(&context, "foo"),
421 TypeAttribute::new(FunctionType::new(&context, &[struct_type], &[]).into()),
422 {
423 let block = Block::new(&[(struct_type, location)]);
424
425 block.append_operation(extract_value(
426 &context,
427 block.argument(0).unwrap().into(),
428 DenseI64ArrayAttribute::new(&context, &[0]),
429 integer_type,
430 location,
431 ));
432
433 block.append_operation(func::r#return(&[], location));
434
435 let region = Region::new();
436 region.append_block(block);
437 region
438 },
439 &[],
440 location,
441 ));
442
443 convert_module(&context, &mut module);
444
445 assert!(module.as_operation().verify());
446 insta::assert_snapshot!(module.as_operation());
447 }
448
449 #[test]
450 fn compile_get_element_ptr() {
451 let context = create_test_context();
452
453 let location = Location::unknown(&context);
454 let mut module = Module::new(location);
455 let integer_type = IntegerType::new(&context, 64).into();
456 let ptr_type = r#type::pointer(&context, 0);
457
458 module.body().append_operation(func::func(
459 &context,
460 StringAttribute::new(&context, "foo"),
461 TypeAttribute::new(FunctionType::new(&context, &[ptr_type], &[]).into()),
462 {
463 let block = Block::new(&[(ptr_type, location)]);
464
465 block.append_operation(get_element_ptr(
466 &context,
467 block.argument(0).unwrap().into(),
468 DenseI32ArrayAttribute::new(&context, &[42]),
469 integer_type,
470 ptr_type,
471 location,
472 ));
473
474 block.append_operation(func::r#return(&[], location));
475
476 let region = Region::new();
477 region.append_block(block);
478 region
479 },
480 &[],
481 location,
482 ));
483
484 convert_module(&context, &mut module);
485
486 assert!(module.as_operation().verify());
487 insta::assert_snapshot!(module.as_operation());
488 }
489
490 #[test]
491 fn compile_get_element_ptr_dynamic() {
492 let context = create_test_context();
493
494 let location = Location::unknown(&context);
495 let mut module = Module::new(location);
496 let integer_type = IntegerType::new(&context, 64).into();
497 let ptr_type = r#type::pointer(&context, 0);
498
499 module.body().append_operation(func::func(
500 &context,
501 StringAttribute::new(&context, "foo"),
502 TypeAttribute::new(FunctionType::new(&context, &[ptr_type], &[]).into()),
503 {
504 let block = Block::new(&[(ptr_type, location)]);
505
506 let index = block
507 .append_operation(arith::constant(
508 &context,
509 IntegerAttribute::new(integer_type, 42).into(),
510 location,
511 ))
512 .result(0)
513 .unwrap()
514 .into();
515
516 block.append_operation(get_element_ptr_dynamic(
517 &context,
518 block.argument(0).unwrap().into(),
519 &[index],
520 integer_type,
521 ptr_type,
522 location,
523 ));
524
525 block.append_operation(func::r#return(&[], location));
526
527 let region = Region::new();
528 region.append_block(block);
529 region
530 },
531 &[],
532 location,
533 ));
534
535 convert_module(&context, &mut module);
536
537 assert!(module.as_operation().verify());
538 insta::assert_snapshot!(module.as_operation());
539 }
540
541 #[test]
542 fn compile_insert_value() {
543 let context = create_test_context();
544
545 let location = Location::unknown(&context);
546 let mut module = Module::new(location);
547 let integer_type = IntegerType::new(&context, 64).into();
548 let struct_type = r#type::r#struct(&context, &[integer_type], false);
549
550 module.body().append_operation(func::func(
551 &context,
552 StringAttribute::new(&context, "foo"),
553 TypeAttribute::new(FunctionType::new(&context, &[struct_type], &[]).into()),
554 {
555 let block = Block::new(&[(struct_type, location)]);
556 let value = block
557 .append_operation(arith::constant(
558 &context,
559 IntegerAttribute::new(integer_type, 42).into(),
560 location,
561 ))
562 .result(0)
563 .unwrap()
564 .into();
565
566 block.append_operation(insert_value(
567 &context,
568 block.argument(0).unwrap().into(),
569 DenseI64ArrayAttribute::new(&context, &[0]),
570 value,
571 location,
572 ));
573
574 block.append_operation(func::r#return(&[], location));
575
576 let region = Region::new();
577 region.append_block(block);
578 region
579 },
580 &[],
581 location,
582 ));
583
584 convert_module(&context, &mut module);
585
586 assert!(module.as_operation().verify());
587 insta::assert_snapshot!(module.as_operation());
588 }
589
590 #[test]
591 fn compile_zero() {
592 let context = create_test_context();
593
594 let location = Location::unknown(&context);
595 let mut module = Module::new(location);
596 let integer_type = IntegerType::new(&context, 64).into();
597
598 module.body().append_operation(func::func(
599 &context,
600 StringAttribute::new(&context, "foo"),
601 TypeAttribute::new(FunctionType::new(&context, &[], &[integer_type]).into()),
602 {
603 let block = Block::new(&[]);
604
605 let operation = block.append_operation(zero(integer_type, location));
606
607 block.append_operation(func::r#return(
608 &[operation.result(0).unwrap().into()],
609 location,
610 ));
611
612 let region = Region::new();
613 region.append_block(block);
614 region
615 },
616 &[],
617 location,
618 ));
619
620 convert_module(&context, &mut module);
621
622 assert!(module.as_operation().verify());
623 insta::assert_snapshot!(module.as_operation());
624 }
625
626 #[test]
627 fn compile_null_ptr() {
628 let context = create_test_context();
629
630 let location = Location::unknown(&context);
631 let mut module = Module::new(location);
632 let ptr_type = r#type::pointer(&context, 0);
633
634 module.body().append_operation(func::func(
635 &context,
636 StringAttribute::new(&context, "foo"),
637 TypeAttribute::new(FunctionType::new(&context, &[], &[ptr_type]).into()),
638 {
639 let block = Block::new(&[]);
640
641 let operation = block.append_operation(zero(ptr_type, location));
642
643 block.append_operation(func::r#return(
644 &[operation.result(0).unwrap().into()],
645 location,
646 ));
647
648 let region = Region::new();
649 region.append_block(block);
650 region
651 },
652 &[],
653 location,
654 ));
655
656 convert_module(&context, &mut module);
657
658 assert!(module.as_operation().verify());
659 insta::assert_snapshot!(module.as_operation());
660 }
661
662 #[test]
663 fn compile_undefined() {
664 let context = create_test_context();
665
666 let location = Location::unknown(&context);
667 let mut module = Module::new(location);
668 let struct_type =
669 r#type::r#struct(&context, &[IntegerType::new(&context, 64).into()], false);
670
671 module.body().append_operation(func::func(
672 &context,
673 StringAttribute::new(&context, "foo"),
674 TypeAttribute::new(FunctionType::new(&context, &[struct_type], &[]).into()),
675 {
676 let block = Block::new(&[(struct_type, location)]);
677
678 block.append_operation(undef(struct_type, location));
679
680 block.append_operation(func::r#return(&[], location));
681
682 let region = Region::new();
683 region.append_block(block);
684 region
685 },
686 &[],
687 location,
688 ));
689
690 convert_module(&context, &mut module);
691
692 assert!(module.as_operation().verify());
693 insta::assert_snapshot!(module.as_operation());
694 }
695
696 #[test]
697 fn compile_poison() {
698 let context = create_test_context();
699
700 let location = Location::unknown(&context);
701 let mut module = Module::new(location);
702 let struct_type =
703 r#type::r#struct(&context, &[IntegerType::new(&context, 64).into()], false);
704
705 module.body().append_operation(func::func(
706 &context,
707 StringAttribute::new(&context, "foo"),
708 TypeAttribute::new(FunctionType::new(&context, &[struct_type], &[]).into()),
709 {
710 let block = Block::new(&[(struct_type, location)]);
711
712 block.append_operation(poison(struct_type, location));
713
714 block.append_operation(func::r#return(&[], location));
715
716 let region = Region::new();
717 region.append_block(block);
718 region
719 },
720 &[],
721 location,
722 ));
723
724 convert_module(&context, &mut module);
725
726 assert!(module.as_operation().verify());
727 insta::assert_snapshot!(module.as_operation());
728 }
729
730 #[test]
731 fn compile_alloca() {
732 let context = create_test_context();
733
734 let location = Location::unknown(&context);
735 let mut module = Module::new(location);
736 let integer_type = IntegerType::new(&context, 64).into();
737 let ptr_type = r#type::pointer(&context, 0);
738
739 module.body().append_operation(func::func(
740 &context,
741 StringAttribute::new(&context, "foo"),
742 TypeAttribute::new(FunctionType::new(&context, &[integer_type], &[]).into()),
743 {
744 let block = Block::new(&[(integer_type, location)]);
745
746 block.append_operation(alloca(
747 &context,
748 block.argument(0).unwrap().into(),
749 ptr_type,
750 location,
751 AllocaOptions::new().elem_type(Some(TypeAttribute::new(integer_type))),
752 ));
753
754 block.append_operation(func::r#return(&[], location));
755
756 let region = Region::new();
757 region.append_block(block);
758 region
759 },
760 &[],
761 location,
762 ));
763
764 convert_module(&context, &mut module);
765
766 assert!(module.as_operation().verify());
767 insta::assert_snapshot!(module.as_operation());
768 }
769
770 #[test]
771 fn compile_store() {
772 let context = create_test_context();
773
774 let location = Location::unknown(&context);
775 let mut module = Module::new(location);
776 let integer_type = IntegerType::new(&context, 64).into();
777 let ptr_type = r#type::pointer(&context, 0);
778
779 module.body().append_operation(func::func(
780 &context,
781 StringAttribute::new(&context, "foo"),
782 TypeAttribute::new(FunctionType::new(&context, &[ptr_type, integer_type], &[]).into()),
783 {
784 let block = Block::new(&[(ptr_type, location), (integer_type, location)]);
785
786 block.append_operation(store(
787 &context,
788 block.argument(1).unwrap().into(),
789 block.argument(0).unwrap().into(),
790 location,
791 Default::default(),
792 ));
793
794 block.append_operation(func::r#return(&[], location));
795
796 let region = Region::new();
797 region.append_block(block);
798 region
799 },
800 &[],
801 location,
802 ));
803
804 convert_module(&context, &mut module);
805
806 assert!(module.as_operation().verify());
807 insta::assert_snapshot!(module.as_operation());
808 }
809
810 #[test]
811 fn compile_load() {
812 let context = create_test_context();
813
814 let location = Location::unknown(&context);
815 let mut module = Module::new(location);
816 let integer_type = IntegerType::new(&context, 64).into();
817 let ptr_type = r#type::pointer(&context, 0);
818
819 module.body().append_operation(func::func(
820 &context,
821 StringAttribute::new(&context, "foo"),
822 TypeAttribute::new(FunctionType::new(&context, &[ptr_type], &[]).into()),
823 {
824 let block = Block::new(&[(ptr_type, location)]);
825
826 block.append_operation(load(
827 &context,
828 block.argument(0).unwrap().into(),
829 integer_type,
830 location,
831 Default::default(),
832 ));
833
834 block.append_operation(func::r#return(&[], location));
835
836 let region = Region::new();
837 region.append_block(block);
838 region
839 },
840 &[],
841 location,
842 ));
843
844 convert_module(&context, &mut module);
845
846 assert!(module.as_operation().verify());
847 insta::assert_snapshot!(module.as_operation());
848 }
849
850 #[test]
851 fn compile_store_extra() {
852 let context = create_test_context();
853
854 let location = Location::unknown(&context);
855 let mut module = Module::new(location);
856 let integer_type = IntegerType::new(&context, 64).into();
857 let ptr_type = r#type::pointer(&context, 0);
858
859 module.body().append_operation(func::func(
860 &context,
861 StringAttribute::new(&context, "foo"),
862 TypeAttribute::new(FunctionType::new(&context, &[ptr_type, integer_type], &[]).into()),
863 {
864 let block = Block::new(&[(ptr_type, location), (integer_type, location)]);
865
866 block.append_operation(store(
867 &context,
868 block.argument(1).unwrap().into(),
869 block.argument(0).unwrap().into(),
870 location,
871 LoadStoreOptions::new()
872 .align(Some(IntegerAttribute::new(integer_type, 4)))
873 .volatile(true)
874 .nontemporal(true),
875 ));
876
877 block.append_operation(func::r#return(&[], location));
878
879 let region = Region::new();
880 region.append_block(block);
881 region
882 },
883 &[],
884 location,
885 ));
886
887 convert_module(&context, &mut module);
888
889 assert!(module.as_operation().verify());
890 insta::assert_snapshot!(module.as_operation());
891 }
892
893 #[test]
894 fn compile_func() {
895 let context = create_test_context();
896
897 let location = Location::unknown(&context);
898 let mut module = Module::new(location);
899 let integer_type = IntegerType::new(&context, 32).into();
900
901 module.body().append_operation(func(
902 &context,
903 StringAttribute::new(&context, "printf"),
904 TypeAttribute::new(function(integer_type, &[pointer(&context, 0)], true)),
905 Region::new(),
906 &[(
907 Identifier::new(&context, "linkage"),
908 linkage(&context, Linkage::External),
909 )],
910 location,
911 ));
912
913 convert_module(&context, &mut module);
914
915 assert!(module.as_operation().verify());
916 insta::assert_snapshot!(module.as_operation());
917 }
918
919 #[test]
920 fn compile_return() {
921 let context = create_test_context();
922
923 let location = Location::unknown(&context);
924 let mut module = Module::new(location);
925 let integer_type = IntegerType::new(&context, 64).into();
926 let struct_type = r#type::r#struct(&context, &[integer_type], false);
927
928 module.body().append_operation(func::func(
929 &context,
930 StringAttribute::new(&context, "foo_none"),
931 TypeAttribute::new(FunctionType::new(&context, &[], &[]).into()),
932 {
933 let block = Block::new(&[]);
934
935 block.append_operation(r#return(None, location));
936
937 let region = Region::new();
938 region.append_block(block);
939 region
940 },
941 &[],
942 location,
943 ));
944
945 module.body().append_operation(func::func(
946 &context,
947 StringAttribute::new(&context, "foo"),
948 TypeAttribute::new(FunctionType::new(&context, &[struct_type], &[struct_type]).into()),
949 {
950 let block = Block::new(&[(struct_type, location)]);
951
952 block.append_operation(r#return(Some(block.argument(0).unwrap().into()), location));
953
954 let region = Region::new();
955 region.append_block(block);
956 region
957 },
958 &[],
959 location,
960 ));
961
962 convert_module(&context, &mut module);
963
964 assert!(module.as_operation().verify());
965 insta::assert_snapshot!(module.as_operation());
966 }
967
968 #[test]
969 fn compile_intr_ctlz() {
970 let context = create_test_context();
971
972 let location = Location::unknown(&context);
973 let mut module = Module::new(location);
974 let integer_type = IntegerType::new(&context, 64).into();
975
976 module.body().append_operation(func::func(
977 &context,
978 StringAttribute::new(&context, "foo"),
979 TypeAttribute::new(
980 FunctionType::new(&context, &[integer_type], &[integer_type]).into(),
981 ),
982 {
983 let block = Block::new(&[(integer_type, location)]);
984
985 let res = block
986 .append_operation(intr_ctlz(
987 &context,
988 block.argument(0).unwrap().into(),
989 true,
990 integer_type,
991 location,
992 ))
993 .result(0)
994 .unwrap()
995 .into();
996
997 block.append_operation(func::r#return(&[res], location));
998
999 let region = Region::new();
1000 region.append_block(block);
1001 region
1002 },
1003 &[],
1004 location,
1005 ));
1006
1007 convert_module(&context, &mut module);
1008
1009 assert!(module.as_operation().verify());
1010 insta::assert_snapshot!(module.as_operation());
1011 }
1012
1013 #[test]
1014 fn compile_intr_cttz() {
1015 let context = create_test_context();
1016
1017 let location = Location::unknown(&context);
1018 let mut module = Module::new(location);
1019 let integer_type = IntegerType::new(&context, 64).into();
1020
1021 module.body().append_operation(func::func(
1022 &context,
1023 StringAttribute::new(&context, "foo"),
1024 TypeAttribute::new(
1025 FunctionType::new(&context, &[integer_type], &[integer_type]).into(),
1026 ),
1027 {
1028 let block = Block::new(&[(integer_type, location)]);
1029
1030 let res = block
1031 .append_operation(intr_cttz(
1032 &context,
1033 block.argument(0).unwrap().into(),
1034 true,
1035 integer_type,
1036 location,
1037 ))
1038 .result(0)
1039 .unwrap()
1040 .into();
1041
1042 block.append_operation(func::r#return(&[res], location));
1043
1044 let region = Region::new();
1045 region.append_block(block);
1046 region
1047 },
1048 &[],
1049 location,
1050 ));
1051
1052 convert_module(&context, &mut module);
1053
1054 assert!(module.as_operation().verify());
1055 insta::assert_snapshot!(module.as_operation());
1056 }
1057
1058 #[test]
1059 fn compile_intr_ctpop() {
1060 let context = create_test_context();
1061
1062 let location = Location::unknown(&context);
1063 let mut module = Module::new(location);
1064 let integer_type = IntegerType::new(&context, 64).into();
1065
1066 module.body().append_operation(func::func(
1067 &context,
1068 StringAttribute::new(&context, "foo"),
1069 TypeAttribute::new(
1070 FunctionType::new(&context, &[integer_type], &[integer_type]).into(),
1071 ),
1072 {
1073 let block = Block::new(&[(integer_type, location)]);
1074
1075 let res = block
1076 .append_operation(intr_ctpop(
1077 block.argument(0).unwrap().into(),
1078 integer_type,
1079 location,
1080 ))
1081 .result(0)
1082 .unwrap()
1083 .into();
1084
1085 block.append_operation(func::r#return(&[res], location));
1086
1087 let region = Region::new();
1088 region.append_block(block);
1089 region
1090 },
1091 &[],
1092 location,
1093 ));
1094
1095 convert_module(&context, &mut module);
1096
1097 assert!(module.as_operation().verify());
1098 insta::assert_snapshot!(module.as_operation());
1099 }
1100
1101 #[test]
1102 fn compile_intr_bswap() {
1103 let context = create_test_context();
1104
1105 let location = Location::unknown(&context);
1106 let mut module = Module::new(location);
1107 let integer_type = IntegerType::new(&context, 64).into();
1108
1109 module.body().append_operation(func::func(
1110 &context,
1111 StringAttribute::new(&context, "foo"),
1112 TypeAttribute::new(
1113 FunctionType::new(&context, &[integer_type], &[integer_type]).into(),
1114 ),
1115 {
1116 let block = Block::new(&[(integer_type, location)]);
1117
1118 let res = block
1119 .append_operation(intr_bswap(
1120 block.argument(0).unwrap().into(),
1121 integer_type,
1122 location,
1123 ))
1124 .result(0)
1125 .unwrap()
1126 .into();
1127
1128 block.append_operation(func::r#return(&[res], location));
1129
1130 let region = Region::new();
1131 region.append_block(block);
1132 region
1133 },
1134 &[],
1135 location,
1136 ));
1137
1138 convert_module(&context, &mut module);
1139
1140 assert!(module.as_operation().verify());
1141 insta::assert_snapshot!(module.as_operation());
1142 }
1143
1144 #[test]
1145 fn compile_intr_bitreverse() {
1146 let context = create_test_context();
1147
1148 let location = Location::unknown(&context);
1149 let mut module = Module::new(location);
1150 let integer_type = IntegerType::new(&context, 64).into();
1151
1152 module.body().append_operation(func::func(
1153 &context,
1154 StringAttribute::new(&context, "foo"),
1155 TypeAttribute::new(
1156 FunctionType::new(&context, &[integer_type], &[integer_type]).into(),
1157 ),
1158 {
1159 let block = Block::new(&[(integer_type, location)]);
1160
1161 let res = block
1162 .append_operation(intr_bitreverse(
1163 block.argument(0).unwrap().into(),
1164 integer_type,
1165 location,
1166 ))
1167 .result(0)
1168 .unwrap()
1169 .into();
1170
1171 block.append_operation(func::r#return(&[res], location));
1172
1173 let region = Region::new();
1174 region.append_block(block);
1175 region
1176 },
1177 &[],
1178 location,
1179 ));
1180
1181 convert_module(&context, &mut module);
1182
1183 assert!(module.as_operation().verify());
1184 insta::assert_snapshot!(module.as_operation());
1185 }
1186
1187 #[test]
1188 fn compile_intr_abs() {
1189 let context = create_test_context();
1190
1191 let location = Location::unknown(&context);
1192 let mut module = Module::new(location);
1193 let integer_type = IntegerType::new(&context, 64).into();
1194
1195 module.body().append_operation(func::func(
1196 &context,
1197 StringAttribute::new(&context, "foo"),
1198 TypeAttribute::new(
1199 FunctionType::new(&context, &[integer_type], &[integer_type]).into(),
1200 ),
1201 {
1202 let block = Block::new(&[(integer_type, location)]);
1203
1204 let res = block
1205 .append_operation(intr_abs(
1206 &context,
1207 block.argument(0).unwrap().into(),
1208 true,
1209 integer_type,
1210 location,
1211 ))
1212 .result(0)
1213 .unwrap()
1214 .into();
1215
1216 block.append_operation(func::r#return(&[res], location));
1217
1218 let region = Region::new();
1219 region.append_block(block);
1220 region
1221 },
1222 &[],
1223 location,
1224 ));
1225
1226 convert_module(&context, &mut module);
1227
1228 assert!(module.as_operation().verify());
1229 insta::assert_snapshot!(module.as_operation());
1230 }
1231
1232 #[test]
1233 fn compile_zext() {
1234 let context = create_test_context();
1235
1236 let location = Location::unknown(&context);
1237 let mut module = Module::new(location);
1238 let integer_type = IntegerType::new(&context, 64).into();
1239 let integer_double_type = IntegerType::new(&context, 128).into();
1240
1241 module.body().append_operation(func::func(
1242 &context,
1243 StringAttribute::new(&context, "foo"),
1244 TypeAttribute::new(
1245 FunctionType::new(&context, &[integer_type], &[integer_double_type]).into(),
1246 ),
1247 {
1248 let block = Block::new(&[(integer_type, location)]);
1249
1250 let res = block
1251 .append_operation(zext(
1252 block.argument(0).unwrap().into(),
1253 integer_double_type,
1254 location,
1255 ))
1256 .result(0)
1257 .unwrap()
1258 .into();
1259
1260 block.append_operation(func::r#return(&[res], location));
1261
1262 let region = Region::new();
1263 region.append_block(block);
1264 region
1265 },
1266 &[],
1267 location,
1268 ));
1269
1270 convert_module(&context, &mut module);
1271
1272 assert!(module.as_operation().verify());
1273 insta::assert_snapshot!(module.as_operation());
1274 }
1275}