[llvm-c] Add LLVMGetAggregateElement() function

This adds LLVMGetAggregateElement() as a wrapper for
Constant::getAggregateElement(), which allows fetching a
struct/array/vector element without handling different possible
underlying representations.

As the changed echo test shows, previously you for example had to
treat ConstantArray (use LLVMGetOperand) and ConstantDataArray
(use LLVMGetElementAsConstant) separately, not to mention all the
other possible representations (like PoisonValue).

I've deprecated LLVMGetElementAsConstant() in favor of the new
function, which is strictly more powerful (but I could be convinced
to drop the deprecation).

This is partly motivated by https://reviews.llvm.org/D125795,
which drops LLVMConstExtractValue() because the underlying constant
expression no longer exists. This function could previously be used
as a poor man's getAggregateElement().

Differential Revision: https://reviews.llvm.org/D128417
This commit is contained in:
Nikita Popov 2022-06-23 11:44:20 +02:00
parent 0eb17a9d86
commit da34966a5a
4 changed files with 36 additions and 31 deletions

View File

@ -151,6 +151,13 @@ Changes to the C API
resolving the best cast operation given a source value and destination type.
This function is a direct wrapper of ``CastInst::getCastOpcode``.
* Add ``LLVMGetAggregateElement`` function as a wrapper for
``Constant::getAggregateElement``, which can be used to fetch an element of a
constant struct, array or vector, independently of the underlying
representation. The ``LLVMGetElementAsConstant`` function is deprecated in
favor of the new function, which works on all constant aggregates, rather than
only instances of ``ConstantDataSequential``.
Changes to the Go bindings
--------------------------

View File

@ -2111,12 +2111,24 @@ LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy,
LLVMValueRef *ConstantVals,
unsigned Count);
/**
* Get element of a constant aggregate (struct, array or vector) at the
* specified index. Returns null if the index is out of range, or it's not
* possible to determine the element (e.g., because the constant is a
* constant expression.)
*
* @see llvm::Constant::getAggregateElement()
*/
LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx);
/**
* Get an element at specified index as a constant.
*
* @see ConstantDataSequential::getElementAsConstant()
*/
LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef C, unsigned idx);
LLVM_ATTRIBUTE_C_DEPRECATED(
LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef C, unsigned idx),
"Use LLVMGetAggregateElement instead");
/**
* Create a ConstantVector from values.

View File

@ -1445,6 +1445,10 @@ LLVMValueRef LLVMConstString(const char *Str, unsigned Length,
DontNullTerminate);
}
LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));
}
LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef C, unsigned idx) {
return wrap(unwrap<ConstantDataSequential>(C)->getElementAsConstant(idx));
}

View File

@ -301,25 +301,16 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
return LLVMConstNull(TypeCloner(M).Clone(Cst));
}
// Try constant array
if (LLVMIsAConstantArray(Cst)) {
check_value_kind(Cst, LLVMConstantArrayValueKind);
// Try constant array or constant data array
if (LLVMIsAConstantArray(Cst) || LLVMIsAConstantDataArray(Cst)) {
check_value_kind(Cst, LLVMIsAConstantArray(Cst)
? LLVMConstantArrayValueKind
: LLVMConstantDataArrayValueKind);
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
unsigned EltCount = LLVMGetArrayLength(Ty);
SmallVector<LLVMValueRef, 8> Elts;
for (unsigned i = 0; i < EltCount; i++)
Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M));
return LLVMConstArray(LLVMGetElementType(Ty), Elts.data(), EltCount);
}
// Try constant data array
if (LLVMIsAConstantDataArray(Cst)) {
check_value_kind(Cst, LLVMConstantDataArrayValueKind);
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
unsigned EltCount = LLVMGetArrayLength(Ty);
SmallVector<LLVMValueRef, 8> Elts;
for (unsigned i = 0; i < EltCount; i++)
Elts.push_back(clone_constant(LLVMGetElementAsConstant(Cst, i), M));
Elts.push_back(clone_constant(LLVMGetAggregateElement(Cst, i), M));
return LLVMConstArray(LLVMGetElementType(Ty), Elts.data(), EltCount);
}
@ -369,25 +360,16 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
report_fatal_error("ConstantFP is not supported");
}
// Try ConstantVector
if (LLVMIsAConstantVector(Cst)) {
check_value_kind(Cst, LLVMConstantVectorValueKind);
// Try ConstantVector or ConstantDataVector
if (LLVMIsAConstantVector(Cst) || LLVMIsAConstantDataVector(Cst)) {
check_value_kind(Cst, LLVMIsAConstantVector(Cst)
? LLVMConstantVectorValueKind
: LLVMConstantDataVectorValueKind);
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
unsigned EltCount = LLVMGetVectorSize(Ty);
SmallVector<LLVMValueRef, 8> Elts;
for (unsigned i = 0; i < EltCount; i++)
Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M));
return LLVMConstVector(Elts.data(), EltCount);
}
// Try ConstantDataVector
if (LLVMIsAConstantDataVector(Cst)) {
check_value_kind(Cst, LLVMConstantDataVectorValueKind);
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
unsigned EltCount = LLVMGetVectorSize(Ty);
SmallVector<LLVMValueRef, 8> Elts;
for (unsigned i = 0; i < EltCount; i++)
Elts.push_back(clone_constant(LLVMGetElementAsConstant(Cst, i), M));
Elts.push_back(clone_constant(LLVMGetAggregateElement(Cst, i), M));
return LLVMConstVector(Elts.data(), EltCount);
}