diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index 298b716801da7..f9cdb35e932c3 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -201,6 +201,10 @@ Changes to the C API * `LLVMConstNUWMul` * `LLVMConstNSWMul` +* Added `LLVMConstDataArray` and `LLVMGetRawDataValues` to allow creating and + reading `ConstantDataArray` values without needing extra `LLVMValueRef`s for + individual elements. + Changes to the CodeGen infrastructure ------------------------------------- diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 871e5eb8457d7..596531c93a949 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -2350,6 +2350,16 @@ LLVMBool LLVMIsConstantString(LLVMValueRef c); */ const char *LLVMGetAsString(LLVMValueRef c, size_t *Length); +/** + * Get the raw, underlying bytes of the given constant data sequential. + * + * This is the same as LLVMGetAsString except it works for all constant data + * sequentials, not just i8 arrays. + * + * @see ConstantDataSequential::getRawDataValues() + */ +const char *LLVMGetRawDataValues(LLVMValueRef c, size_t *SizeInBytes); + /** * Create an anonymous ConstantStruct with the specified values. * @@ -2388,6 +2398,18 @@ LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, LLVMValueRef LLVMConstArray2(LLVMTypeRef ElementTy, LLVMValueRef *ConstantVals, uint64_t Length); +/** + * Create a ConstantDataArray from raw values. + * + * ElementTy must be one of i8, i16, i32, i64, half, bfloat, float, or double. + * Data points to a contiguous buffer of raw values in the host endianness. The + * element count is inferred from the element type and the data size in bytes. + * + * @see llvm::ConstantDataArray::getRaw() + */ +LLVMValueRef LLVMConstDataArray(LLVMTypeRef ElementTy, const char *Data, + size_t SizeInBytes); + /** * Create a non-anonymous ConstantStruct from values. * diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index f4b03e8cb8aa3..55be0dd6e523d 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -1643,6 +1643,12 @@ const char *LLVMGetAsString(LLVMValueRef C, size_t *Length) { return Str.data(); } +const char *LLVMGetRawDataValues(LLVMValueRef C, size_t *SizeInBytes) { + StringRef Str = unwrap(C)->getRawDataValues(); + *SizeInBytes = Str.size(); + return Str.data(); +} + LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, LLVMValueRef *ConstantVals, unsigned Length) { ArrayRef V(unwrap(ConstantVals, Length), Length); @@ -1655,6 +1661,13 @@ LLVMValueRef LLVMConstArray2(LLVMTypeRef ElementTy, LLVMValueRef *ConstantVals, return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length), V)); } +LLVMValueRef LLVMConstDataArray(LLVMTypeRef ElementTy, const char *Data, + size_t SizeInBytes) { + Type *Ty = unwrap(ElementTy); + size_t Len = SizeInBytes / (Ty->getPrimitiveSizeInBits() / 8); + return wrap(ConstantDataArray::getRaw(StringRef(Data, SizeInBytes), Len, Ty)); +} + LLVMValueRef LLVMConstStructInContext(LLVMContextRef C, LLVMValueRef *ConstantVals, unsigned Count, LLVMBool Packed) { diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll index c4b932034b501..0a688afab6125 100644 --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -17,6 +17,7 @@ module asm "classical GAS" @arr = linkonce_odr global [5 x i8] [ i8 2, i8 3, i8 5, i8 7, i8 11 ] @str = private unnamed_addr constant [13 x i8] c"hello world\0A\00" @locStr = private local_unnamed_addr constant [13 x i8] c"hello world\0A\00" +@caLarge = private constant [2 x i128] [ i128 12345, i128 67890 ] @hidden = hidden global i32 7 @protected = protected global i32 23 @section = global i32 27, section ".custom" diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 4173e49e60a04..3ec40fdba0bad 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -317,11 +317,18 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) { return LLVMConstNull(TypeCloner(M).Clone(Cst)); } - // Try constant array or constant data array - if (LLVMIsAConstantArray(Cst) || LLVMIsAConstantDataArray(Cst)) { - check_value_kind(Cst, LLVMIsAConstantArray(Cst) - ? LLVMConstantArrayValueKind - : LLVMConstantDataArrayValueKind); + // Try constant data array + if (LLVMIsAConstantDataArray(Cst)) { + check_value_kind(Cst, LLVMConstantDataArrayValueKind); + LLVMTypeRef Ty = TypeCloner(M).Clone(Cst); + size_t SizeInBytes; + const char *Data = LLVMGetRawDataValues(Cst, &SizeInBytes); + return LLVMConstDataArray(LLVMGetElementType(Ty), Data, SizeInBytes); + } + + // Try constant array + if (LLVMIsAConstantArray(Cst)) { + check_value_kind(Cst, LLVMConstantArrayValueKind); LLVMTypeRef Ty = TypeCloner(M).Clone(Cst); uint64_t EltCount = LLVMGetArrayLength2(Ty); SmallVector Elts;