Skip to content

Commit 52c7a3d

Browse files
authored
Merge pull request rust-lang#151 from willtunnels/build_malloc-fix
Build malloc fix
2 parents 0a864eb + 78f9e53 commit 52c7a3d

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

src/builder.rs

+36-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::basic_block::BasicBlock;
1212
use crate::values::{AggregateValue, AggregateValueEnum, AsValueRef, BasicValue, BasicValueEnum, PhiValue, FunctionValue, IntValue, PointerValue, VectorValue, InstructionValue, GlobalValue, IntMathValue, FloatMathValue, PointerMathValue, InstructionOpcode, CallSiteValue};
1313
#[llvm_versions(3.9..=latest)]
1414
use crate::values::StructValue;
15-
use crate::types::{AsTypeRef, BasicType, IntMathType, FloatMathType, PointerType, PointerMathType};
15+
use crate::types::{AsTypeRef, BasicType, BasicTypeEnum, IntMathType, FloatMathType, PointerType, PointerMathType};
1616

1717
use std::ffi::CString;
1818
use std::marker::PhantomData;
@@ -348,25 +348,56 @@ impl<'ctx> Builder<'ctx> {
348348
}
349349

350350
// TODOC: Heap allocation
351-
pub fn build_malloc<T: BasicType<'ctx>>(&self, ty: T, name: &str) -> PointerValue<'ctx> {
351+
pub fn build_malloc<T: BasicType<'ctx>>(&self, ty: T, name: &str) -> Result<PointerValue<'ctx>, &'static str> {
352+
// LLVMBulidMalloc segfaults if ty is unsized
353+
let is_sized = match ty.as_basic_type_enum() {
354+
BasicTypeEnum::ArrayType(ty) => ty.is_sized(),
355+
BasicTypeEnum::FloatType(ty) => ty.is_sized(),
356+
BasicTypeEnum::IntType(ty) => ty.is_sized(),
357+
BasicTypeEnum::PointerType(ty) => ty.is_sized(),
358+
BasicTypeEnum::StructType(ty) => ty.is_sized(),
359+
BasicTypeEnum::VectorType(ty) => ty.is_sized(),
360+
};
361+
if !is_sized {
362+
return Err("Cannot build malloc call for an unsized type");
363+
}
364+
352365
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
353366

354367
let value = unsafe {
355368
LLVMBuildMalloc(self.builder, ty.as_type_ref(), c_string.as_ptr())
356369
};
357370

358-
PointerValue::new(value)
371+
Ok(PointerValue::new(value))
359372
}
360373

361374
// TODOC: Heap allocation
362-
pub fn build_array_malloc<T: BasicType<'ctx>>(&self, ty: T, size: IntValue<'ctx>, name: &str) -> PointerValue<'ctx> {
375+
pub fn build_array_malloc<T: BasicType<'ctx>>(
376+
&self,
377+
ty: T,
378+
size: IntValue<'ctx>,
379+
name: &str
380+
) -> Result<PointerValue<'ctx>, &'static str> {
381+
// LLVMBulidArrayMalloc segfaults if ty is unsized
382+
let is_sized = match ty.as_basic_type_enum() {
383+
BasicTypeEnum::ArrayType(ty) => ty.is_sized(),
384+
BasicTypeEnum::FloatType(ty) => ty.is_sized(),
385+
BasicTypeEnum::IntType(ty) => ty.is_sized(),
386+
BasicTypeEnum::PointerType(ty) => ty.is_sized(),
387+
BasicTypeEnum::StructType(ty) => ty.is_sized(),
388+
BasicTypeEnum::VectorType(ty) => ty.is_sized(),
389+
};
390+
if !is_sized {
391+
return Err("Cannot build array malloc call for an unsized type");
392+
}
393+
363394
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
364395

365396
let value = unsafe {
366397
LLVMBuildArrayMalloc(self.builder, ty.as_type_ref(), size.as_value_ref(), c_string.as_ptr())
367398
};
368399

369-
PointerValue::new(value)
400+
Ok(PointerValue::new(value))
370401
}
371402

372403
// SubType: <P>(&self, ptr: PointerValue<P>) -> InstructionValue {

tests/all/test_values.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,7 @@ fn test_allocations() {
903903
let module = context.create_module("my_mod");
904904
let void_type = context.void_type();
905905
let i32_type = context.i32_type();
906+
let unsized_type = context.opaque_struct_type("my_struct");
906907
let i32_three = i32_type.const_int(3, false);
907908
let fn_type = void_type.fn_type(&[], false);
908909
let fn_value = module.add_function("my_func", fn_type, None);
@@ -927,11 +928,21 @@ fn test_allocations() {
927928

928929
let heap_ptr = builder.build_malloc(i32_type, "heap_ptr");
929930

930-
assert_eq!(*heap_ptr.get_type().print_to_string(), *CString::new("i32*").unwrap());
931+
assert!(heap_ptr.is_ok());
932+
assert_eq!(*heap_ptr.unwrap().get_type().print_to_string(), *CString::new("i32*").unwrap());
931933

932934
let heap_array = builder.build_array_malloc(i32_type, i32_three, "heap_array");
933935

934-
assert_eq!(*heap_array.get_type().print_to_string(), *CString::new("i32*").unwrap());
936+
assert!(heap_array.is_ok());
937+
assert_eq!(*heap_array.unwrap().get_type().print_to_string(), *CString::new("i32*").unwrap());
938+
939+
let bad_malloc_res = builder.build_malloc(unsized_type, "");
940+
941+
assert!(bad_malloc_res.is_err());
942+
943+
let bad_array_malloc_res = builder.build_array_malloc(unsized_type, i32_three, "");
944+
945+
assert!(bad_array_malloc_res.is_err());
935946
}
936947

937948
#[test]

0 commit comments

Comments
 (0)