blob: 97883863ed68c608ce9cb6ce0335fd6482f26c7a [file] [log] [blame]
Amaury Sechete8ea7d82016-02-04 23:26:19 +00001//===-- echo.cpp - tool for testing libLLVM and llvm-c API ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the --echo commands in llvm-c-test.
11//
12// This command uses the C API to read a module and output an exact copy of it
13// as output. It is used to check that the resulting module matches the input
14// to validate that the C API can read and write modules properly.
15//
16//===----------------------------------------------------------------------===//
17
18#include "llvm-c-test.h"
19#include "llvm/ADT/DenseMap.h"
Amaury Secheta82042e2016-02-09 22:36:41 +000020#include "llvm/Support/ErrorHandling.h"
Amaury Sechete8ea7d82016-02-04 23:26:19 +000021
22#include <stdio.h>
23#include <stdlib.h>
24
25using namespace llvm;
26
27// Provide DenseMapInfo for C API opaque types.
28template<typename T>
29struct CAPIDenseMap {};
30
31// The default DenseMapInfo require to know about pointer alignement.
32// Because the C API uses opaques pointer types, their alignement is unknown.
33// As a result, we need to roll out our own implementation.
34template<typename T>
35struct CAPIDenseMap<T*> {
36 struct CAPIDenseMapInfo {
37 static inline T* getEmptyKey() {
38 uintptr_t Val = static_cast<uintptr_t>(-1);
39 return reinterpret_cast<T*>(Val);
40 }
41 static inline T* getTombstoneKey() {
42 uintptr_t Val = static_cast<uintptr_t>(-2);
43 return reinterpret_cast<T*>(Val);
44 }
45 static unsigned getHashValue(const T *PtrVal) {
46 return hash_value(PtrVal);
47 }
48 static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
49 };
50
51 typedef DenseMap<T*, T*, CAPIDenseMapInfo> Map;
52};
53
54typedef CAPIDenseMap<LLVMValueRef>::Map ValueMap;
Amaury Secheta82042e2016-02-09 22:36:41 +000055typedef CAPIDenseMap<LLVMBasicBlockRef>::Map BasicBlockMap;
Amaury Sechete8ea7d82016-02-04 23:26:19 +000056
57static 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);
Amaury Secheta82042e2016-02-09 22:36:41 +000084 for (unsigned i = 0; i < ParamCount; i++)
Amaury Sechete8ea7d82016-02-04 23:26:19 +000085 Params[i] = clone_type(Params[i], Ctx);
Amaury Sechete8ea7d82016-02-04 23:26:19 +000086 }
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;
98 }
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 }
123
124 fprintf(stderr, "%d is not a supported typekind\n", Kind);
125 exit(-1);
126}
127
128static LLVMValueRef clone_literal(LLVMValueRef Src, LLVMContextRef Ctx) {
129 LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
130
131 LLVMTypeKind Kind = LLVMGetTypeKind(Ty);
132 switch (Kind) {
133 case LLVMIntegerTypeKind:
134 return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);
135 default:
136 break;
137 }
138
139 fprintf(stderr, "%d is not a supported constant typekind\n", Kind);
140 exit(-1);
141}
142
143static LLVMModuleRef get_module(LLVMBuilderRef Builder) {
144 LLVMBasicBlockRef BB = LLVMGetInsertBlock(Builder);
145 LLVMValueRef Fn = LLVMGetBasicBlockParent(BB);
146 return LLVMGetGlobalParent(Fn);
147}
148
Amaury Secheta82042e2016-02-09 22:36:41 +0000149static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000150
Amaury Secheta82042e2016-02-09 22:36:41 +0000151struct FunCloner {
152 LLVMValueRef Fun;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000153
Amaury Secheta82042e2016-02-09 22:36:41 +0000154 ValueMap VMap;
155 BasicBlockMap BBMap;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000156
Amaury Secheta82042e2016-02-09 22:36:41 +0000157 FunCloner(LLVMValueRef Src, LLVMValueRef Dst)
158 : Fun(Dst), VMap(clone_params(Src, Dst)) {}
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000159
Amaury Secheta82042e2016-02-09 22:36:41 +0000160 // Try to clone everything in the llvm::Value hierarchy.
161 LLVMValueRef CloneValue(LLVMValueRef Src, LLVMBuilderRef Builder) {
162 const char *Name = LLVMGetValueName(Src);
163
164 // First, the value may be constant.
165 if (LLVMIsAConstant(Src)) {
166 LLVMModuleRef M = get_module(Builder);
167
168 // Maybe it is a symbol
169 if (LLVMIsAGlobalValue(Src)) {
170 // Try function
171 LLVMValueRef Dst = LLVMGetNamedFunction(M, Name);
172 if (Dst != nullptr)
173 return Dst;
174
175 // Try global variable
176 Dst = LLVMGetNamedGlobal(M, Name);
177 if (Dst != nullptr)
178 return Dst;
179
180 fprintf(stderr, "Could not find @%s\n", Name);
181 exit(-1);
182 }
183
184 // Try literal
185 LLVMContextRef Ctx = LLVMGetModuleContext(M);
186 return clone_literal(Src, Ctx);
187 }
188
189 // Try undef
190 if (LLVMIsUndef(Src)) {
191 LLVMContextRef Ctx = LLVMGetModuleContext(get_module(Builder));
192 LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
193 return LLVMGetUndef(Ty);
194 }
195
196 // Check if this is something we already computed.
197 {
198 auto i = VMap.find(Src);
199 if (i != VMap.end())
200 return i->second;
201 }
202
203 // We tried everything, it must be an instruction
204 // that hasn't been generated already.
205 LLVMValueRef Dst = nullptr;
206
207 LLVMOpcode Op = LLVMGetInstructionOpcode(Src);
208 switch(Op) {
209 case LLVMRet: {
210 int OpCount = LLVMGetNumOperands(Src);
211 if (OpCount == 0)
212 Dst = LLVMBuildRetVoid(Builder);
213 else
214 Dst = LLVMBuildRet(Builder, CloneValue(LLVMGetOperand(Src, 0),
215 Builder));
216 break;
217 }
218 case LLVMBr: {
219 LLVMBasicBlockRef SrcBB = LLVMValueAsBasicBlock(LLVMGetOperand(Src, 0));
220 Dst = LLVMBuildBr(Builder, DeclareBB(SrcBB));
221 break;
222 }
223 case LLVMSwitch:
224 case LLVMIndirectBr:
225 case LLVMInvoke:
226 break;
227 case LLVMUnreachable:
228 Dst = LLVMBuildUnreachable(Builder);
229 break;
230 case LLVMAdd: {
231 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
232 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
233 Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);
234 break;
235 }
236 case LLVMSub: {
237 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
238 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
239 Dst = LLVMBuildSub(Builder, LHS, RHS, Name);
240 break;
241 }
242 case LLVMMul: {
243 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
244 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
245 Dst = LLVMBuildMul(Builder, LHS, RHS, Name);
246 break;
247 }
248 case LLVMUDiv: {
249 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
250 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
251 Dst = LLVMBuildUDiv(Builder, LHS, RHS, Name);
252 break;
253 }
254 case LLVMSDiv: {
255 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
256 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
257 Dst = LLVMBuildSDiv(Builder, LHS, RHS, Name);
258 break;
259 }
260 case LLVMURem: {
261 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
262 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
263 Dst = LLVMBuildURem(Builder, LHS, RHS, Name);
264 break;
265 }
266 case LLVMSRem: {
267 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
268 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
269 Dst = LLVMBuildSRem(Builder, LHS, RHS, Name);
270 break;
271 }
272 case LLVMShl: {
273 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
274 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
275 Dst = LLVMBuildShl(Builder, LHS, RHS, Name);
276 break;
277 }
278 case LLVMLShr: {
279 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
280 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
281 Dst = LLVMBuildLShr(Builder, LHS, RHS, Name);
282 break;
283 }
284 case LLVMAShr: {
285 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
286 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
287 Dst = LLVMBuildAShr(Builder, LHS, RHS, Name);
288 break;
289 }
290 case LLVMAnd: {
291 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
292 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
293 Dst = LLVMBuildAnd(Builder, LHS, RHS, Name);
294 break;
295 }
296 case LLVMOr: {
297 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
298 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
299 Dst = LLVMBuildOr(Builder, LHS, RHS, Name);
300 break;
301 }
302 case LLVMXor: {
303 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
304 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
305 Dst = LLVMBuildXor(Builder, LHS, RHS, Name);
306 break;
307 }
308 case LLVMAlloca: {
Amaury Sechet1dcf5772016-02-09 22:50:53 +0000309 LLVMContextRef Ctx = LLVMGetModuleContext(get_module(Builder));
310 LLVMTypeRef Ty = clone_type(LLVMGetAllocatedType(Src), Ctx);
Amaury Secheta82042e2016-02-09 22:36:41 +0000311 Dst = LLVMBuildAlloca(Builder, Ty, Name);
312 break;
313 }
314 case LLVMCall: {
315 int ArgCount = LLVMGetNumOperands(Src) - 1;
316 SmallVector<LLVMValueRef, 8> Args;
317 for (int i = 0; i < ArgCount; i++)
318 Args.push_back(CloneValue(LLVMGetOperand(Src, i), Builder));
319 LLVMValueRef Fn = CloneValue(LLVMGetOperand(Src, ArgCount), Builder);
320 Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
321 break;
322 }
323 default:
324 break;
325 }
326
327 if (Dst == nullptr) {
328 fprintf(stderr, "%d is not a supported opcode\n", Op);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000329 exit(-1);
330 }
331
Amaury Secheta82042e2016-02-09 22:36:41 +0000332 return VMap[Src] = Dst;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000333 }
334
Amaury Secheta82042e2016-02-09 22:36:41 +0000335 LLVMBasicBlockRef DeclareBB(LLVMBasicBlockRef Src) {
336 // Check if this is something we already computed.
337 {
338 auto i = BBMap.find(Src);
339 if (i != BBMap.end()) {
340 return i->second;
341 }
342 }
343
344 const char *Name = LLVMGetBasicBlockName(Src);
345
346 LLVMValueRef V = LLVMBasicBlockAsValue(Src);
347 if (!LLVMValueIsBasicBlock(V) || LLVMValueAsBasicBlock(V) != Src)
348 report_fatal_error("Basic block is not a basic block\n");
349
350 const char *VName = LLVMGetValueName(V);
351 if (Name != VName)
352 report_fatal_error("Basic block name mismatch");
353
354 LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Fun, Name);
355 return BBMap[Src] = BB;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000356 }
357
Amaury Secheta82042e2016-02-09 22:36:41 +0000358 LLVMBasicBlockRef CloneBB(LLVMBasicBlockRef Src) {
359 LLVMBasicBlockRef BB = DeclareBB(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000360
Amaury Secheta82042e2016-02-09 22:36:41 +0000361 // Make sure ordering is correct.
362 LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Src);
363 if (Prev)
364 LLVMMoveBasicBlockAfter(BB, DeclareBB(Prev));
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000365
Amaury Secheta82042e2016-02-09 22:36:41 +0000366 LLVMValueRef First = LLVMGetFirstInstruction(Src);
367 LLVMValueRef Last = LLVMGetLastInstruction(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000368
Amaury Secheta82042e2016-02-09 22:36:41 +0000369 if (First == nullptr) {
370 if (Last != nullptr) {
371 fprintf(stderr, "Has no first instruction, but last one\n");
372 exit(-1);
373 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000374
Amaury Secheta82042e2016-02-09 22:36:41 +0000375 return BB;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000376 }
377
Amaury Secheta82042e2016-02-09 22:36:41 +0000378 LLVMContextRef Ctx = LLVMGetModuleContext(LLVMGetGlobalParent(Fun));
379 LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
380 LLVMPositionBuilderAtEnd(Builder, BB);
381
382 LLVMValueRef Cur = First;
383 LLVMValueRef Next = nullptr;
384 while(true) {
385 CloneValue(Cur, Builder);
386 Next = LLVMGetNextInstruction(Cur);
387 if (Next == nullptr) {
388 if (Cur != Last) {
389 fprintf(stderr, "Final instruction does not match Last\n");
390 exit(-1);
391 }
392
393 break;
394 }
395
396 LLVMValueRef Prev = LLVMGetPreviousInstruction(Next);
397 if (Prev != Cur) {
398 fprintf(stderr, "Next.Previous instruction is not Current\n");
399 exit(-1);
400 }
401
402 Cur = Next;
403 }
404
405 LLVMDisposeBuilder(Builder);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000406 return BB;
407 }
408
Amaury Secheta82042e2016-02-09 22:36:41 +0000409 void CloneBBs(LLVMValueRef Src) {
410 unsigned Count = LLVMCountBasicBlocks(Src);
411 if (Count == 0)
412 return;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000413
Amaury Secheta82042e2016-02-09 22:36:41 +0000414 LLVMBasicBlockRef First = LLVMGetFirstBasicBlock(Src);
415 LLVMBasicBlockRef Last = LLVMGetLastBasicBlock(Src);
416
417 LLVMBasicBlockRef Cur = First;
418 LLVMBasicBlockRef Next = nullptr;
419 while(true) {
420 CloneBB(Cur);
421 Count--;
422 Next = LLVMGetNextBasicBlock(Cur);
423 if (Next == nullptr) {
424 if (Cur != Last) {
425 fprintf(stderr, "Final basic block does not match Last\n");
426 exit(-1);
427 }
428
429 break;
430 }
431
432 LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Next);
433 if (Prev != Cur) {
434 fprintf(stderr, "Next.Previous basic bloc is not Current\n");
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000435 exit(-1);
436 }
437
Amaury Secheta82042e2016-02-09 22:36:41 +0000438 Cur = Next;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000439 }
440
Amaury Secheta82042e2016-02-09 22:36:41 +0000441 if (Count != 0) {
442 fprintf(stderr, "Basic block count does not match iterration\n");
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000443 exit(-1);
444 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000445 }
Amaury Secheta82042e2016-02-09 22:36:41 +0000446};
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000447
448static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst) {
449 unsigned Count = LLVMCountParams(Src);
450 if (Count != LLVMCountParams(Dst)) {
451 fprintf(stderr, "Parameter count mismatch\n");
452 exit(-1);
453 }
454
455 ValueMap VMap;
456 if (Count == 0)
457 return VMap;
458
459 LLVMValueRef SrcFirst = LLVMGetFirstParam(Src);
460 LLVMValueRef DstFirst = LLVMGetFirstParam(Dst);
461 LLVMValueRef SrcLast = LLVMGetLastParam(Src);
462 LLVMValueRef DstLast = LLVMGetLastParam(Dst);
463
464 LLVMValueRef SrcCur = SrcFirst;
465 LLVMValueRef DstCur = DstFirst;
466 LLVMValueRef SrcNext = nullptr;
467 LLVMValueRef DstNext = nullptr;
468 while (true) {
469 const char *Name = LLVMGetValueName(SrcCur);
470 LLVMSetValueName(DstCur, Name);
471
472 VMap[SrcCur] = DstCur;
473
474 Count--;
475 SrcNext = LLVMGetNextParam(SrcCur);
476 DstNext = LLVMGetNextParam(DstCur);
477 if (SrcNext == nullptr && DstNext == nullptr) {
478 if (SrcCur != SrcLast) {
479 fprintf(stderr, "SrcLast param does not match End\n");
480 exit(-1);
481 }
482
483 if (DstCur != DstLast) {
484 fprintf(stderr, "DstLast param does not match End\n");
485 exit(-1);
486 }
487
488 break;
489 }
490
491 if (SrcNext == nullptr) {
492 fprintf(stderr, "SrcNext was unexpectedly null\n");
493 exit(-1);
494 }
495
496 if (DstNext == nullptr) {
497 fprintf(stderr, "DstNext was unexpectedly null\n");
498 exit(-1);
499 }
500
501 LLVMValueRef SrcPrev = LLVMGetPreviousParam(SrcNext);
502 if (SrcPrev != SrcCur) {
503 fprintf(stderr, "SrcNext.Previous param is not Current\n");
504 exit(-1);
505 }
506
507 LLVMValueRef DstPrev = LLVMGetPreviousParam(DstNext);
508 if (DstPrev != DstCur) {
509 fprintf(stderr, "DstNext.Previous param is not Current\n");
510 exit(-1);
511 }
512
513 SrcCur = SrcNext;
514 DstCur = DstNext;
515 }
516
517 if (Count != 0) {
518 fprintf(stderr, "Parameter count does not match iteration\n");
519 exit(-1);
520 }
521
522 return VMap;
523}
524
525static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef Dst) {
526 const char *Name = LLVMGetValueName(Src);
527 LLVMValueRef Fun = LLVMGetNamedFunction(Dst, Name);
528 if (Fun != nullptr)
529 return Fun;
530
531 LLVMTypeRef SrcTy = LLVMTypeOf(Src);
532 LLVMTypeRef DstTy = clone_type(SrcTy, LLVMGetModuleContext(Dst));
533 LLVMTypeRef FunTy = LLVMGetElementType(DstTy);
534
535 Fun = LLVMAddFunction(Dst, Name, FunTy);
Amaury Secheta82042e2016-02-09 22:36:41 +0000536 FunCloner FC(Src, Fun);
537 FC.CloneBBs(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000538
539 return Fun;
540}
541
542static void clone_functions(LLVMModuleRef Src, LLVMModuleRef Dst) {
543 LLVMValueRef Begin = LLVMGetFirstFunction(Src);
544 LLVMValueRef End = LLVMGetLastFunction(Src);
545
546 LLVMValueRef Cur = Begin;
547 LLVMValueRef Next = nullptr;
548 while (true) {
549 clone_function(Cur, Dst);
550 Next = LLVMGetNextFunction(Cur);
551 if (Next == nullptr) {
552 if (Cur != End) {
553 fprintf(stderr, "Last function does not match End\n");
554 exit(-1);
555 }
556
557 break;
558 }
559
560 LLVMValueRef Prev = LLVMGetPreviousFunction(Next);
561 if (Prev != Cur) {
562 fprintf(stderr, "Next.Previous function is not Current\n");
563 exit(-1);
564 }
565
566 Cur = Next;
567 }
568}
569
Benjamin Kramer9a3bd232016-02-05 13:31:14 +0000570int llvm_echo(void) {
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000571 LLVMEnablePrettyStackTrace();
572
Benjamin Kramer9a3bd232016-02-05 13:31:14 +0000573 LLVMModuleRef Src = llvm_load_module(false, true);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000574
575 LLVMContextRef Ctx = LLVMContextCreate();
576 LLVMModuleRef Dst = LLVMModuleCreateWithNameInContext("<stdin>", Ctx);
577
578 clone_functions(Src, Dst);
579 char *Str = LLVMPrintModuleToString(Dst);
580 fputs(Str, stdout);
581
582 LLVMDisposeMessage(Str);
583 LLVMDisposeModule(Dst);
584 LLVMContextDispose(Ctx);
585
586 return 0;
587}