@@ -945,16 +945,61 @@ impl Builder {
945
945
}
946
946
}
947
947
948
- // REVIEW: How does LLVM treat out of bound index? Maybe we should return an Option?
949
- // or is that only in bounds GEP
950
- pub fn build_extract_value < AV : AggregateValue > ( & self , value : AV , index : u32 , name : & str ) -> BasicValueEnum {
948
+ /// Builds an extract value instruction which extracts a `BasicValueEnum`
949
+ /// from a struct or array.
950
+ ///
951
+ /// # Example
952
+ ///
953
+ /// ```no_run
954
+ /// use inkwell::context::Context;
955
+ ///
956
+ /// let context = Context::create();
957
+ /// let module = context.create_module("av");
958
+ /// let void_type = context.void_type();
959
+ /// let f32_type = context.f32_type();
960
+ /// let i32_type = context.i32_type();
961
+ /// let struct_type = context.struct_type(&[i32_type.into(), f32_type.into()], false);
962
+ /// let array_type = i32_type.array_type(3);
963
+ /// let fn_type = void_type.fn_type(&[], false);
964
+ /// let fn_value = module.add_function("av_fn", fn_type, None);
965
+ /// let builder = context.create_builder();
966
+ /// let entry = fn_value.append_basic_block("entry");
967
+ ///
968
+ /// builder.position_at_end(&entry);
969
+ ///
970
+ /// let array_alloca = builder.build_alloca(array_type, "array_alloca");
971
+ /// let array = builder.build_load(array_alloca, "array_load").into_array_value();
972
+ /// let const_int1 = i32_type.const_int(2, false);
973
+ /// let const_int2 = i32_type.const_int(5, false);
974
+ /// let const_int3 = i32_type.const_int(6, false);
975
+ ///
976
+ /// assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_some());
977
+ /// assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_some());
978
+ /// assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_some());
979
+ /// assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_none());
980
+ ///
981
+ /// assert!(builder.build_extract_value(array, 0, "extract").unwrap().is_int_value());
982
+ /// assert!(builder.build_extract_value(array, 1, "extract").unwrap().is_int_value());
983
+ /// assert!(builder.build_extract_value(array, 2, "extract").unwrap().is_int_value());
984
+ /// assert!(builder.build_extract_value(array, 3, "extract").is_none());
985
+ /// ```
986
+ pub fn build_extract_value < AV : AggregateValue > ( & self , agg : AV , index : u32 , name : & str ) -> Option < BasicValueEnum > {
987
+ let size = match agg. as_aggregate_value_enum ( ) {
988
+ AggregateValueEnum :: ArrayValue ( av) => av. get_type ( ) . len ( ) ,
989
+ AggregateValueEnum :: StructValue ( sv) => sv. get_type ( ) . count_fields ( ) ,
990
+ } ;
991
+
992
+ if index >= size {
993
+ return None ;
994
+ }
995
+
951
996
let c_string = CString :: new ( name) . expect ( "Conversion to CString failed unexpectedly" ) ;
952
997
953
998
let value = unsafe {
954
- LLVMBuildExtractValue ( self . builder , value . as_value_ref ( ) , index, c_string. as_ptr ( ) )
999
+ LLVMBuildExtractValue ( self . builder , agg . as_value_ref ( ) , index, c_string. as_ptr ( ) )
955
1000
} ;
956
1001
957
- BasicValueEnum :: new ( value)
1002
+ Some ( BasicValueEnum :: new ( value) )
958
1003
}
959
1004
960
1005
/// Builds an insert value instruction which inserts a `BasicValue` into a struct
0 commit comments