forked from OSchip/llvm-project
Add support for struct in C API test
Summary: As per title. This also include extra support for insertvalue and extracvalue. Reviewers: bogner, chandlerc, echristo, dblaikie, joker.eph, Wallbraker Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D17055 llvm-svn: 260335
This commit is contained in:
parent
ae06ca0c7e
commit
aad935378f
|
@ -2575,6 +2575,30 @@ LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index);
|
|||
*/
|
||||
LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCCoreValueInstructionExtractValue ExtractValue
|
||||
* @defgroup LLVMCCoreValueInstructionInsertValue InsertValue
|
||||
*
|
||||
* Functions in this group only apply to instructions that map to
|
||||
* llvm::ExtractValue and llvm::InsertValue instances.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtain the number of indices.
|
||||
*/
|
||||
unsigned LLVMGetNumIndices(LLVMValueRef Inst);
|
||||
|
||||
/**
|
||||
* Obtain the indices as an array.
|
||||
*/
|
||||
const unsigned *LLVMGetIndices(LLVMValueRef Inst);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -2160,6 +2160,28 @@ LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index) {
|
|||
return wrap(unwrap<PHINode>(PhiNode)->getIncomingBlock(Index));
|
||||
}
|
||||
|
||||
/*--.. Operations on extractvalue and insertvalue nodes ....................--*/
|
||||
|
||||
unsigned LLVMGetNumIndices(LLVMValueRef Inst) {
|
||||
auto *I = unwrap(Inst);
|
||||
if (auto *EV = dyn_cast<ExtractValueInst>(I))
|
||||
return EV->getNumIndices();
|
||||
if (auto *IV = dyn_cast<InsertValueInst>(I))
|
||||
return IV->getNumIndices();
|
||||
llvm_unreachable(
|
||||
"LLVMGetNumIndices applies only to extractvalue and insertvalue!");
|
||||
}
|
||||
|
||||
const unsigned *LLVMGetIndices(LLVMValueRef Inst) {
|
||||
auto *I = unwrap(Inst);
|
||||
if (auto *EV = dyn_cast<ExtractValueInst>(I))
|
||||
return EV->getIndices().data();
|
||||
if (auto *IV = dyn_cast<InsertValueInst>(I))
|
||||
return IV->getIndices().data();
|
||||
llvm_unreachable(
|
||||
"LLVMGetIndices applies only to extractvalue and insertvalue!");
|
||||
}
|
||||
|
||||
|
||||
/*===-- Instruction builders ----------------------------------------------===*/
|
||||
|
||||
|
|
|
@ -2,9 +2,19 @@
|
|||
; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo
|
||||
; RUN: diff -w %t.orig %t.echo
|
||||
|
||||
%S = type { i64, %S* }
|
||||
|
||||
define { i64, %S* } @unpackrepack(%S %s) {
|
||||
%1 = extractvalue %S %s, 0
|
||||
%2 = extractvalue %S %s, 1
|
||||
%3 = insertvalue { i64, %S* } undef, %S* %2, 1
|
||||
%4 = insertvalue { i64, %S* } %3, i64 %1, 0
|
||||
ret { i64, %S* } %4
|
||||
}
|
||||
|
||||
declare void @decl()
|
||||
|
||||
; TODO: label, struct and metadata types
|
||||
; TODO: label and metadata types
|
||||
define void @types() {
|
||||
%1 = alloca half
|
||||
%2 = alloca float
|
||||
|
|
|
@ -54,90 +54,120 @@ struct CAPIDenseMap<T*> {
|
|||
typedef CAPIDenseMap<LLVMValueRef>::Map ValueMap;
|
||||
typedef CAPIDenseMap<LLVMBasicBlockRef>::Map BasicBlockMap;
|
||||
|
||||
static LLVMTypeRef clone_type(LLVMTypeRef Src, LLVMContextRef Ctx) {
|
||||
LLVMTypeKind Kind = LLVMGetTypeKind(Src);
|
||||
switch (Kind) {
|
||||
case LLVMVoidTypeKind:
|
||||
return LLVMVoidTypeInContext(Ctx);
|
||||
case LLVMHalfTypeKind:
|
||||
return LLVMHalfTypeInContext(Ctx);
|
||||
case LLVMFloatTypeKind:
|
||||
return LLVMFloatTypeInContext(Ctx);
|
||||
case LLVMDoubleTypeKind:
|
||||
return LLVMDoubleTypeInContext(Ctx);
|
||||
case LLVMX86_FP80TypeKind:
|
||||
return LLVMX86FP80TypeInContext(Ctx);
|
||||
case LLVMFP128TypeKind:
|
||||
return LLVMFP128TypeInContext(Ctx);
|
||||
case LLVMPPC_FP128TypeKind:
|
||||
return LLVMPPCFP128TypeInContext(Ctx);
|
||||
case LLVMLabelTypeKind:
|
||||
return LLVMLabelTypeInContext(Ctx);
|
||||
case LLVMIntegerTypeKind:
|
||||
return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));
|
||||
case LLVMFunctionTypeKind: {
|
||||
unsigned ParamCount = LLVMCountParamTypes(Src);
|
||||
LLVMTypeRef* Params = nullptr;
|
||||
if (ParamCount > 0) {
|
||||
Params = (LLVMTypeRef*) malloc(ParamCount * sizeof(LLVMTypeRef));
|
||||
LLVMGetParamTypes(Src, Params);
|
||||
for (unsigned i = 0; i < ParamCount; i++)
|
||||
Params[i] = clone_type(Params[i], Ctx);
|
||||
struct TypeCloner {
|
||||
LLVMModuleRef M;
|
||||
LLVMContextRef Ctx;
|
||||
|
||||
TypeCloner(LLVMModuleRef M): M(M), Ctx(LLVMGetModuleContext(M)) {}
|
||||
|
||||
LLVMTypeRef Clone(LLVMTypeRef Src) {
|
||||
LLVMTypeKind Kind = LLVMGetTypeKind(Src);
|
||||
switch (Kind) {
|
||||
case LLVMVoidTypeKind:
|
||||
return LLVMVoidTypeInContext(Ctx);
|
||||
case LLVMHalfTypeKind:
|
||||
return LLVMHalfTypeInContext(Ctx);
|
||||
case LLVMFloatTypeKind:
|
||||
return LLVMFloatTypeInContext(Ctx);
|
||||
case LLVMDoubleTypeKind:
|
||||
return LLVMDoubleTypeInContext(Ctx);
|
||||
case LLVMX86_FP80TypeKind:
|
||||
return LLVMX86FP80TypeInContext(Ctx);
|
||||
case LLVMFP128TypeKind:
|
||||
return LLVMFP128TypeInContext(Ctx);
|
||||
case LLVMPPC_FP128TypeKind:
|
||||
return LLVMPPCFP128TypeInContext(Ctx);
|
||||
case LLVMLabelTypeKind:
|
||||
return LLVMLabelTypeInContext(Ctx);
|
||||
case LLVMIntegerTypeKind:
|
||||
return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));
|
||||
case LLVMFunctionTypeKind: {
|
||||
unsigned ParamCount = LLVMCountParamTypes(Src);
|
||||
LLVMTypeRef* Params = nullptr;
|
||||
if (ParamCount > 0) {
|
||||
Params = (LLVMTypeRef*) malloc(ParamCount * sizeof(LLVMTypeRef));
|
||||
LLVMGetParamTypes(Src, Params);
|
||||
for (unsigned i = 0; i < ParamCount; i++)
|
||||
Params[i] = Clone(Params[i]);
|
||||
}
|
||||
|
||||
LLVMTypeRef FunTy = LLVMFunctionType(Clone(LLVMGetReturnType(Src)),
|
||||
Params, ParamCount,
|
||||
LLVMIsFunctionVarArg(Src));
|
||||
if (ParamCount > 0)
|
||||
free(Params);
|
||||
return FunTy;
|
||||
}
|
||||
case LLVMStructTypeKind: {
|
||||
LLVMTypeRef S = nullptr;
|
||||
const char *Name = LLVMGetStructName(Src);
|
||||
if (Name) {
|
||||
S = LLVMGetTypeByName(M, Name);
|
||||
if (S)
|
||||
return S;
|
||||
S = LLVMStructCreateNamed(Ctx, Name);
|
||||
if (LLVMIsOpaqueStruct(Src))
|
||||
return S;
|
||||
}
|
||||
|
||||
LLVMTypeRef FunTy = LLVMFunctionType(
|
||||
clone_type(LLVMGetReturnType(Src), Ctx),
|
||||
Params, ParamCount,
|
||||
LLVMIsFunctionVarArg(Src)
|
||||
);
|
||||
|
||||
if (ParamCount > 0)
|
||||
free(Params);
|
||||
|
||||
return FunTy;
|
||||
unsigned EltCount = LLVMCountStructElementTypes(Src);
|
||||
SmallVector<LLVMTypeRef, 8> Elts;
|
||||
for (unsigned i = 0; i < EltCount; i++)
|
||||
Elts.push_back(Clone(LLVMStructGetTypeAtIndex(Src, i)));
|
||||
if (Name)
|
||||
LLVMStructSetBody(S, Elts.data(), EltCount, LLVMIsPackedStruct(Src));
|
||||
else
|
||||
S = LLVMStructTypeInContext(Ctx, Elts.data(), EltCount,
|
||||
LLVMIsPackedStruct(Src));
|
||||
return S;
|
||||
}
|
||||
case LLVMArrayTypeKind:
|
||||
return LLVMArrayType(
|
||||
Clone(LLVMGetElementType(Src)),
|
||||
LLVMGetArrayLength(Src)
|
||||
);
|
||||
case LLVMPointerTypeKind:
|
||||
return LLVMPointerType(
|
||||
Clone(LLVMGetElementType(Src)),
|
||||
LLVMGetPointerAddressSpace(Src)
|
||||
);
|
||||
case LLVMVectorTypeKind:
|
||||
return LLVMVectorType(
|
||||
Clone(LLVMGetElementType(Src)),
|
||||
LLVMGetVectorSize(Src)
|
||||
);
|
||||
case LLVMMetadataTypeKind:
|
||||
break;
|
||||
case LLVMX86_MMXTypeKind:
|
||||
return LLVMX86MMXTypeInContext(Ctx);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case LLVMStructTypeKind:
|
||||
break;
|
||||
case LLVMArrayTypeKind:
|
||||
return LLVMArrayType(
|
||||
clone_type(LLVMGetElementType(Src), Ctx),
|
||||
LLVMGetArrayLength(Src)
|
||||
);
|
||||
case LLVMPointerTypeKind:
|
||||
return LLVMPointerType(
|
||||
clone_type(LLVMGetElementType(Src), Ctx),
|
||||
LLVMGetPointerAddressSpace(Src)
|
||||
);
|
||||
case LLVMVectorTypeKind:
|
||||
return LLVMVectorType(
|
||||
clone_type(LLVMGetElementType(Src), Ctx),
|
||||
LLVMGetVectorSize(Src)
|
||||
);
|
||||
case LLVMMetadataTypeKind:
|
||||
break;
|
||||
case LLVMX86_MMXTypeKind:
|
||||
return LLVMX86MMXTypeInContext(Ctx);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%d is not a supported typekind\n", Kind);
|
||||
exit(-1);
|
||||
}
|
||||
fprintf(stderr, "%d is not a supported typekind\n", Kind);
|
||||
exit(-1);
|
||||
}
|
||||
};
|
||||
|
||||
static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst);
|
||||
|
||||
struct FunCloner {
|
||||
LLVMValueRef Fun;
|
||||
LLVMModuleRef M;
|
||||
LLVMContextRef Ctx;
|
||||
|
||||
ValueMap VMap;
|
||||
BasicBlockMap BBMap;
|
||||
|
||||
FunCloner(LLVMValueRef Src, LLVMValueRef Dst)
|
||||
: Fun(Dst), M(LLVMGetGlobalParent(Fun)), Ctx(LLVMGetModuleContext(M)),
|
||||
VMap(clone_params(Src, Dst)) {}
|
||||
FunCloner(LLVMValueRef Src, LLVMValueRef Dst): Fun(Dst),
|
||||
M(LLVMGetGlobalParent(Fun)), VMap(clone_params(Src, Dst)) {}
|
||||
|
||||
LLVMTypeRef CloneType(LLVMTypeRef Src) {
|
||||
return TypeCloner(M).Clone(Src);
|
||||
}
|
||||
|
||||
LLVMTypeRef CloneType(LLVMValueRef Src) {
|
||||
return CloneType(LLVMTypeOf(Src));
|
||||
}
|
||||
|
||||
// Try to clone everything in the llvm::Value hierarchy.
|
||||
LLVMValueRef CloneValue(LLVMValueRef Src) {
|
||||
|
@ -163,13 +193,13 @@ struct FunCloner {
|
|||
|
||||
// Try literal
|
||||
if (LLVMIsAConstantInt(Src)) {
|
||||
LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
|
||||
LLVMTypeRef Ty = CloneType(Src);
|
||||
return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);
|
||||
}
|
||||
|
||||
// Try undef
|
||||
if (LLVMIsUndef(Src))
|
||||
return LLVMGetUndef(clone_type(LLVMTypeOf(Src), Ctx));
|
||||
return LLVMGetUndef(CloneType(Src));
|
||||
|
||||
// This kind of constant is not supported.
|
||||
report_fatal_error("Unsupported contant type");
|
||||
|
@ -183,6 +213,7 @@ struct FunCloner {
|
|||
}
|
||||
|
||||
if (LLVMIsAInstruction(Src)) {
|
||||
auto Ctx = LLVMGetModuleContext(M);
|
||||
auto Builder = LLVMCreateBuilderInContext(Ctx);
|
||||
auto BB = DeclareBB(LLVMGetInstructionParent(Src));
|
||||
LLVMPositionBuilderAtEnd(Builder, BB);
|
||||
|
@ -323,7 +354,7 @@ struct FunCloner {
|
|||
break;
|
||||
}
|
||||
case LLVMAlloca: {
|
||||
LLVMTypeRef Ty = clone_type(LLVMGetAllocatedType(Src), Ctx);
|
||||
LLVMTypeRef Ty = CloneType(LLVMGetAllocatedType(Src));
|
||||
Dst = LLVMBuildAlloca(Builder, Ty, Name);
|
||||
break;
|
||||
}
|
||||
|
@ -343,6 +374,23 @@ struct FunCloner {
|
|||
Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
|
||||
break;
|
||||
}
|
||||
case LLVMExtractValue: {
|
||||
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
|
||||
if (LLVMGetNumIndices(Src) != 1)
|
||||
report_fatal_error("Expected only one indice");
|
||||
auto I = LLVMGetIndices(Src)[0];
|
||||
Dst = LLVMBuildExtractValue(Builder, Agg, I, Name);
|
||||
break;
|
||||
}
|
||||
case LLVMInsertValue: {
|
||||
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
|
||||
LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1));
|
||||
if (LLVMGetNumIndices(Src) != 1)
|
||||
report_fatal_error("Expected only one indice");
|
||||
auto I = LLVMGetIndices(Src)[0];
|
||||
Dst = LLVMBuildInsertValue(Builder, Agg, V, I, Name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -398,6 +446,7 @@ struct FunCloner {
|
|||
return BB;
|
||||
}
|
||||
|
||||
auto Ctx = LLVMGetModuleContext(M);
|
||||
LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
|
||||
LLVMPositionBuilderAtEnd(Builder, BB);
|
||||
|
||||
|
@ -550,8 +599,7 @@ static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef M) {
|
|||
if (Fun != nullptr)
|
||||
return Fun;
|
||||
|
||||
LLVMTypeRef SrcTy = LLVMTypeOf(Src);
|
||||
LLVMTypeRef DstTy = clone_type(SrcTy, LLVMGetModuleContext(M));
|
||||
LLVMTypeRef DstTy = TypeCloner(M).Clone(LLVMTypeOf(Src));
|
||||
LLVMTypeRef FunTy = LLVMGetElementType(DstTy);
|
||||
|
||||
Fun = LLVMAddFunction(M, Name, FunTy);
|
||||
|
|
Loading…
Reference in New Issue