Skip to content

Commit aad9353

Browse files
committed
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
1 parent ae06ca0 commit aad9353

File tree

4 files changed

+182
-78
lines changed

4 files changed

+182
-78
lines changed

llvm/include/llvm-c/Core.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,6 +2575,30 @@ LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index);
25752575
*/
25762576
LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index);
25772577

2578+
/**
2579+
* @}
2580+
*/
2581+
2582+
/**
2583+
* @defgroup LLVMCCoreValueInstructionExtractValue ExtractValue
2584+
* @defgroup LLVMCCoreValueInstructionInsertValue InsertValue
2585+
*
2586+
* Functions in this group only apply to instructions that map to
2587+
* llvm::ExtractValue and llvm::InsertValue instances.
2588+
*
2589+
* @{
2590+
*/
2591+
2592+
/**
2593+
* Obtain the number of indices.
2594+
*/
2595+
unsigned LLVMGetNumIndices(LLVMValueRef Inst);
2596+
2597+
/**
2598+
* Obtain the indices as an array.
2599+
*/
2600+
const unsigned *LLVMGetIndices(LLVMValueRef Inst);
2601+
25782602
/**
25792603
* @}
25802604
*/

llvm/lib/IR/Core.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,6 +2160,28 @@ LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index) {
21602160
return wrap(unwrap<PHINode>(PhiNode)->getIncomingBlock(Index));
21612161
}
21622162

2163+
/*--.. Operations on extractvalue and insertvalue nodes ....................--*/
2164+
2165+
unsigned LLVMGetNumIndices(LLVMValueRef Inst) {
2166+
auto *I = unwrap(Inst);
2167+
if (auto *EV = dyn_cast<ExtractValueInst>(I))
2168+
return EV->getNumIndices();
2169+
if (auto *IV = dyn_cast<InsertValueInst>(I))
2170+
return IV->getNumIndices();
2171+
llvm_unreachable(
2172+
"LLVMGetNumIndices applies only to extractvalue and insertvalue!");
2173+
}
2174+
2175+
const unsigned *LLVMGetIndices(LLVMValueRef Inst) {
2176+
auto *I = unwrap(Inst);
2177+
if (auto *EV = dyn_cast<ExtractValueInst>(I))
2178+
return EV->getIndices().data();
2179+
if (auto *IV = dyn_cast<InsertValueInst>(I))
2180+
return IV->getIndices().data();
2181+
llvm_unreachable(
2182+
"LLVMGetIndices applies only to extractvalue and insertvalue!");
2183+
}
2184+
21632185

21642186
/*===-- Instruction builders ----------------------------------------------===*/
21652187

llvm/test/Bindings/llvm-c/echo.ll

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22
; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo
33
; RUN: diff -w %t.orig %t.echo
44

5+
%S = type { i64, %S* }
6+
7+
define { i64, %S* } @unpackrepack(%S %s) {
8+
%1 = extractvalue %S %s, 0
9+
%2 = extractvalue %S %s, 1
10+
%3 = insertvalue { i64, %S* } undef, %S* %2, 1
11+
%4 = insertvalue { i64, %S* } %3, i64 %1, 0
12+
ret { i64, %S* } %4
13+
}
14+
515
declare void @decl()
616

7-
; TODO: label, struct and metadata types
17+
; TODO: label and metadata types
818
define void @types() {
919
%1 = alloca half
1020
%2 = alloca float

llvm/tools/llvm-c-test/echo.cpp

Lines changed: 125 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -54,90 +54,120 @@ struct CAPIDenseMap<T*> {
5454
typedef CAPIDenseMap<LLVMValueRef>::Map ValueMap;
5555
typedef CAPIDenseMap<LLVMBasicBlockRef>::Map BasicBlockMap;
5656

57-
static LLVMTypeRef clone_type(LLVMTypeRef Src, LLVMContextRef Ctx) {
58-
LLVMTypeKind Kind = LLVMGetTypeKind(Src);
59-
switch (Kind) {
60-
case LLVMVoidTypeKind:
61-
return LLVMVoidTypeInContext(Ctx);
62-
case LLVMHalfTypeKind:
63-
return LLVMHalfTypeInContext(Ctx);
64-
case LLVMFloatTypeKind:
65-
return LLVMFloatTypeInContext(Ctx);
66-
case LLVMDoubleTypeKind:
67-
return LLVMDoubleTypeInContext(Ctx);
68-
case LLVMX86_FP80TypeKind:
69-
return LLVMX86FP80TypeInContext(Ctx);
70-
case LLVMFP128TypeKind:
71-
return LLVMFP128TypeInContext(Ctx);
72-
case LLVMPPC_FP128TypeKind:
73-
return LLVMPPCFP128TypeInContext(Ctx);
74-
case LLVMLabelTypeKind:
75-
return LLVMLabelTypeInContext(Ctx);
76-
case LLVMIntegerTypeKind:
77-
return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));
78-
case LLVMFunctionTypeKind: {
79-
unsigned ParamCount = LLVMCountParamTypes(Src);
80-
LLVMTypeRef* Params = nullptr;
81-
if (ParamCount > 0) {
82-
Params = (LLVMTypeRef*) malloc(ParamCount * sizeof(LLVMTypeRef));
83-
LLVMGetParamTypes(Src, Params);
84-
for (unsigned i = 0; i < ParamCount; i++)
85-
Params[i] = clone_type(Params[i], Ctx);
86-
}
87-
88-
LLVMTypeRef FunTy = LLVMFunctionType(
89-
clone_type(LLVMGetReturnType(Src), Ctx),
90-
Params, ParamCount,
91-
LLVMIsFunctionVarArg(Src)
92-
);
93-
94-
if (ParamCount > 0)
95-
free(Params);
96-
97-
return FunTy;
57+
struct TypeCloner {
58+
LLVMModuleRef M;
59+
LLVMContextRef Ctx;
60+
61+
TypeCloner(LLVMModuleRef M): M(M), Ctx(LLVMGetModuleContext(M)) {}
62+
63+
LLVMTypeRef Clone(LLVMTypeRef Src) {
64+
LLVMTypeKind Kind = LLVMGetTypeKind(Src);
65+
switch (Kind) {
66+
case LLVMVoidTypeKind:
67+
return LLVMVoidTypeInContext(Ctx);
68+
case LLVMHalfTypeKind:
69+
return LLVMHalfTypeInContext(Ctx);
70+
case LLVMFloatTypeKind:
71+
return LLVMFloatTypeInContext(Ctx);
72+
case LLVMDoubleTypeKind:
73+
return LLVMDoubleTypeInContext(Ctx);
74+
case LLVMX86_FP80TypeKind:
75+
return LLVMX86FP80TypeInContext(Ctx);
76+
case LLVMFP128TypeKind:
77+
return LLVMFP128TypeInContext(Ctx);
78+
case LLVMPPC_FP128TypeKind:
79+
return LLVMPPCFP128TypeInContext(Ctx);
80+
case LLVMLabelTypeKind:
81+
return LLVMLabelTypeInContext(Ctx);
82+
case LLVMIntegerTypeKind:
83+
return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));
84+
case LLVMFunctionTypeKind: {
85+
unsigned ParamCount = LLVMCountParamTypes(Src);
86+
LLVMTypeRef* Params = nullptr;
87+
if (ParamCount > 0) {
88+
Params = (LLVMTypeRef*) malloc(ParamCount * sizeof(LLVMTypeRef));
89+
LLVMGetParamTypes(Src, Params);
90+
for (unsigned i = 0; i < ParamCount; i++)
91+
Params[i] = Clone(Params[i]);
92+
}
93+
94+
LLVMTypeRef FunTy = LLVMFunctionType(Clone(LLVMGetReturnType(Src)),
95+
Params, ParamCount,
96+
LLVMIsFunctionVarArg(Src));
97+
if (ParamCount > 0)
98+
free(Params);
99+
return FunTy;
100+
}
101+
case LLVMStructTypeKind: {
102+
LLVMTypeRef S = nullptr;
103+
const char *Name = LLVMGetStructName(Src);
104+
if (Name) {
105+
S = LLVMGetTypeByName(M, Name);
106+
if (S)
107+
return S;
108+
S = LLVMStructCreateNamed(Ctx, Name);
109+
if (LLVMIsOpaqueStruct(Src))
110+
return S;
111+
}
112+
113+
unsigned EltCount = LLVMCountStructElementTypes(Src);
114+
SmallVector<LLVMTypeRef, 8> Elts;
115+
for (unsigned i = 0; i < EltCount; i++)
116+
Elts.push_back(Clone(LLVMStructGetTypeAtIndex(Src, i)));
117+
if (Name)
118+
LLVMStructSetBody(S, Elts.data(), EltCount, LLVMIsPackedStruct(Src));
119+
else
120+
S = LLVMStructTypeInContext(Ctx, Elts.data(), EltCount,
121+
LLVMIsPackedStruct(Src));
122+
return S;
123+
}
124+
case LLVMArrayTypeKind:
125+
return LLVMArrayType(
126+
Clone(LLVMGetElementType(Src)),
127+
LLVMGetArrayLength(Src)
128+
);
129+
case LLVMPointerTypeKind:
130+
return LLVMPointerType(
131+
Clone(LLVMGetElementType(Src)),
132+
LLVMGetPointerAddressSpace(Src)
133+
);
134+
case LLVMVectorTypeKind:
135+
return LLVMVectorType(
136+
Clone(LLVMGetElementType(Src)),
137+
LLVMGetVectorSize(Src)
138+
);
139+
case LLVMMetadataTypeKind:
140+
break;
141+
case LLVMX86_MMXTypeKind:
142+
return LLVMX86MMXTypeInContext(Ctx);
143+
default:
144+
break;
98145
}
99-
case LLVMStructTypeKind:
100-
break;
101-
case LLVMArrayTypeKind:
102-
return LLVMArrayType(
103-
clone_type(LLVMGetElementType(Src), Ctx),
104-
LLVMGetArrayLength(Src)
105-
);
106-
case LLVMPointerTypeKind:
107-
return LLVMPointerType(
108-
clone_type(LLVMGetElementType(Src), Ctx),
109-
LLVMGetPointerAddressSpace(Src)
110-
);
111-
case LLVMVectorTypeKind:
112-
return LLVMVectorType(
113-
clone_type(LLVMGetElementType(Src), Ctx),
114-
LLVMGetVectorSize(Src)
115-
);
116-
case LLVMMetadataTypeKind:
117-
break;
118-
case LLVMX86_MMXTypeKind:
119-
return LLVMX86MMXTypeInContext(Ctx);
120-
default:
121-
break;
122-
}
123146

124-
fprintf(stderr, "%d is not a supported typekind\n", Kind);
125-
exit(-1);
126-
}
147+
fprintf(stderr, "%d is not a supported typekind\n", Kind);
148+
exit(-1);
149+
}
150+
};
127151

128152
static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst);
129153

130154
struct FunCloner {
131155
LLVMValueRef Fun;
132156
LLVMModuleRef M;
133-
LLVMContextRef Ctx;
134157

135158
ValueMap VMap;
136159
BasicBlockMap BBMap;
137160

138-
FunCloner(LLVMValueRef Src, LLVMValueRef Dst)
139-
: Fun(Dst), M(LLVMGetGlobalParent(Fun)), Ctx(LLVMGetModuleContext(M)),
140-
VMap(clone_params(Src, Dst)) {}
161+
FunCloner(LLVMValueRef Src, LLVMValueRef Dst): Fun(Dst),
162+
M(LLVMGetGlobalParent(Fun)), VMap(clone_params(Src, Dst)) {}
163+
164+
LLVMTypeRef CloneType(LLVMTypeRef Src) {
165+
return TypeCloner(M).Clone(Src);
166+
}
167+
168+
LLVMTypeRef CloneType(LLVMValueRef Src) {
169+
return CloneType(LLVMTypeOf(Src));
170+
}
141171

142172
// Try to clone everything in the llvm::Value hierarchy.
143173
LLVMValueRef CloneValue(LLVMValueRef Src) {
@@ -163,13 +193,13 @@ struct FunCloner {
163193

164194
// Try literal
165195
if (LLVMIsAConstantInt(Src)) {
166-
LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
196+
LLVMTypeRef Ty = CloneType(Src);
167197
return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);
168198
}
169199

170200
// Try undef
171201
if (LLVMIsUndef(Src))
172-
return LLVMGetUndef(clone_type(LLVMTypeOf(Src), Ctx));
202+
return LLVMGetUndef(CloneType(Src));
173203

174204
// This kind of constant is not supported.
175205
report_fatal_error("Unsupported contant type");
@@ -183,6 +213,7 @@ struct FunCloner {
183213
}
184214

185215
if (LLVMIsAInstruction(Src)) {
216+
auto Ctx = LLVMGetModuleContext(M);
186217
auto Builder = LLVMCreateBuilderInContext(Ctx);
187218
auto BB = DeclareBB(LLVMGetInstructionParent(Src));
188219
LLVMPositionBuilderAtEnd(Builder, BB);
@@ -323,7 +354,7 @@ struct FunCloner {
323354
break;
324355
}
325356
case LLVMAlloca: {
326-
LLVMTypeRef Ty = clone_type(LLVMGetAllocatedType(Src), Ctx);
357+
LLVMTypeRef Ty = CloneType(LLVMGetAllocatedType(Src));
327358
Dst = LLVMBuildAlloca(Builder, Ty, Name);
328359
break;
329360
}
@@ -343,6 +374,23 @@ struct FunCloner {
343374
Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
344375
break;
345376
}
377+
case LLVMExtractValue: {
378+
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
379+
if (LLVMGetNumIndices(Src) != 1)
380+
report_fatal_error("Expected only one indice");
381+
auto I = LLVMGetIndices(Src)[0];
382+
Dst = LLVMBuildExtractValue(Builder, Agg, I, Name);
383+
break;
384+
}
385+
case LLVMInsertValue: {
386+
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
387+
LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1));
388+
if (LLVMGetNumIndices(Src) != 1)
389+
report_fatal_error("Expected only one indice");
390+
auto I = LLVMGetIndices(Src)[0];
391+
Dst = LLVMBuildInsertValue(Builder, Agg, V, I, Name);
392+
break;
393+
}
346394
default:
347395
break;
348396
}
@@ -398,6 +446,7 @@ struct FunCloner {
398446
return BB;
399447
}
400448

449+
auto Ctx = LLVMGetModuleContext(M);
401450
LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
402451
LLVMPositionBuilderAtEnd(Builder, BB);
403452

@@ -550,8 +599,7 @@ static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef M) {
550599
if (Fun != nullptr)
551600
return Fun;
552601

553-
LLVMTypeRef SrcTy = LLVMTypeOf(Src);
554-
LLVMTypeRef DstTy = clone_type(SrcTy, LLVMGetModuleContext(M));
602+
LLVMTypeRef DstTy = TypeCloner(M).Clone(LLVMTypeOf(Src));
555603
LLVMTypeRef FunTy = LLVMGetElementType(DstTy);
556604

557605
Fun = LLVMAddFunction(M, Name, FunTy);

0 commit comments

Comments
 (0)