blob: 4e4841b8ed823bbea033f51d71fd08376c5ce769 [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
Amaury Secheta82042e2016-02-09 22:36:41 +0000128static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000129
Amaury Secheta82042e2016-02-09 22:36:41 +0000130struct FunCloner {
131 LLVMValueRef Fun;
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000132 LLVMModuleRef M;
133 LLVMContextRef Ctx;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000134
Amaury Secheta82042e2016-02-09 22:36:41 +0000135 ValueMap VMap;
136 BasicBlockMap BBMap;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000137
Amaury Secheta82042e2016-02-09 22:36:41 +0000138 FunCloner(LLVMValueRef Src, LLVMValueRef Dst)
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000139 : Fun(Dst), M(LLVMGetGlobalParent(Fun)), Ctx(LLVMGetModuleContext(M)),
140 VMap(clone_params(Src, Dst)) {}
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000141
Amaury Secheta82042e2016-02-09 22:36:41 +0000142 // Try to clone everything in the llvm::Value hierarchy.
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000143 LLVMValueRef CloneValue(LLVMValueRef Src) {
Amaury Secheta82042e2016-02-09 22:36:41 +0000144 const char *Name = LLVMGetValueName(Src);
145
146 // First, the value may be constant.
147 if (LLVMIsAConstant(Src)) {
Amaury Secheta82042e2016-02-09 22:36:41 +0000148 // Maybe it is a symbol
149 if (LLVMIsAGlobalValue(Src)) {
150 // Try function
151 LLVMValueRef Dst = LLVMGetNamedFunction(M, Name);
152 if (Dst != nullptr)
153 return Dst;
154
155 // Try global variable
156 Dst = LLVMGetNamedGlobal(M, Name);
157 if (Dst != nullptr)
158 return Dst;
159
160 fprintf(stderr, "Could not find @%s\n", Name);
161 exit(-1);
162 }
163
164 // Try literal
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000165 if (LLVMIsAConstantInt(Src)) {
166 LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
167 return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);
168 }
169
170 // Try undef
171 if (LLVMIsUndef(Src))
172 return LLVMGetUndef(clone_type(LLVMTypeOf(Src), Ctx));
173
174 // This kind of constant is not supported.
175 report_fatal_error("Unsupported contant type");
Amaury Secheta82042e2016-02-09 22:36:41 +0000176 }
177
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000178 // Function argument should always be in the map already.
179 if (LLVMIsAArgument(Src)) {
180 auto i = VMap.find(Src);
181 if (i != VMap.end())
182 return i->second;
Amaury Secheta82042e2016-02-09 22:36:41 +0000183 }
184
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000185 if (LLVMIsAInstruction(Src)) {
186 auto Builder = LLVMCreateBuilderInContext(Ctx);
187 auto BB = DeclareBB(LLVMGetInstructionParent(Src));
188 LLVMPositionBuilderAtEnd(Builder, BB);
189 auto Dst = CloneInstruction(Src, Builder);
190 LLVMDisposeBuilder(Builder);
191 return Dst;
192 }
193
194 fprintf(stderr, "Could not determine the type of %s\n", Name);
195 exit(-1);
196 }
197
198 LLVMValueRef CloneInstruction(LLVMValueRef Src, LLVMBuilderRef Builder) {
199 const char *Name = LLVMGetValueName(Src);
200 if (!LLVMIsAInstruction(Src))
201 report_fatal_error("Expected an instruction");
202
Amaury Secheta82042e2016-02-09 22:36:41 +0000203 // Check if this is something we already computed.
204 {
205 auto i = VMap.find(Src);
206 if (i != VMap.end())
207 return i->second;
208 }
209
210 // We tried everything, it must be an instruction
211 // that hasn't been generated already.
212 LLVMValueRef Dst = nullptr;
213
214 LLVMOpcode Op = LLVMGetInstructionOpcode(Src);
215 switch(Op) {
216 case LLVMRet: {
217 int OpCount = LLVMGetNumOperands(Src);
218 if (OpCount == 0)
219 Dst = LLVMBuildRetVoid(Builder);
220 else
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000221 Dst = LLVMBuildRet(Builder, CloneValue(LLVMGetOperand(Src, 0)));
Amaury Secheta82042e2016-02-09 22:36:41 +0000222 break;
223 }
224 case LLVMBr: {
Amaury Sechete7e62172016-02-09 23:15:02 +0000225 if (!LLVMIsConditional(Src)) {
226 LLVMValueRef SrcOp = LLVMGetOperand(Src, 0);
227 LLVMBasicBlockRef SrcBB = LLVMValueAsBasicBlock(SrcOp);
228 Dst = LLVMBuildBr(Builder, DeclareBB(SrcBB));
229 break;
230 }
231
232 LLVMValueRef Cond = LLVMGetCondition(Src);
233 LLVMValueRef Else = LLVMGetOperand(Src, 1);
234 LLVMBasicBlockRef ElseBB = DeclareBB(LLVMValueAsBasicBlock(Else));
235 LLVMValueRef Then = LLVMGetOperand(Src, 2);
236 LLVMBasicBlockRef ThenBB = DeclareBB(LLVMValueAsBasicBlock(Then));
237 Dst = LLVMBuildCondBr(Builder, Cond, ThenBB, ElseBB);
Amaury Secheta82042e2016-02-09 22:36:41 +0000238 break;
239 }
240 case LLVMSwitch:
241 case LLVMIndirectBr:
242 case LLVMInvoke:
243 break;
244 case LLVMUnreachable:
245 Dst = LLVMBuildUnreachable(Builder);
246 break;
247 case LLVMAdd: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000248 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
249 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000250 Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);
251 break;
252 }
253 case LLVMSub: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000254 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
255 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000256 Dst = LLVMBuildSub(Builder, LHS, RHS, Name);
257 break;
258 }
259 case LLVMMul: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000260 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
261 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000262 Dst = LLVMBuildMul(Builder, LHS, RHS, Name);
263 break;
264 }
265 case LLVMUDiv: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000266 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
267 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000268 Dst = LLVMBuildUDiv(Builder, LHS, RHS, Name);
269 break;
270 }
271 case LLVMSDiv: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000272 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
273 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000274 Dst = LLVMBuildSDiv(Builder, LHS, RHS, Name);
275 break;
276 }
277 case LLVMURem: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000278 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
279 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000280 Dst = LLVMBuildURem(Builder, LHS, RHS, Name);
281 break;
282 }
283 case LLVMSRem: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000284 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
285 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000286 Dst = LLVMBuildSRem(Builder, LHS, RHS, Name);
287 break;
288 }
289 case LLVMShl: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000290 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
291 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000292 Dst = LLVMBuildShl(Builder, LHS, RHS, Name);
293 break;
294 }
295 case LLVMLShr: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000296 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
297 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000298 Dst = LLVMBuildLShr(Builder, LHS, RHS, Name);
299 break;
300 }
301 case LLVMAShr: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000302 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
303 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000304 Dst = LLVMBuildAShr(Builder, LHS, RHS, Name);
305 break;
306 }
307 case LLVMAnd: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000308 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
309 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000310 Dst = LLVMBuildAnd(Builder, LHS, RHS, Name);
311 break;
312 }
313 case LLVMOr: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000314 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
315 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000316 Dst = LLVMBuildOr(Builder, LHS, RHS, Name);
317 break;
318 }
319 case LLVMXor: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000320 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
321 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000322 Dst = LLVMBuildXor(Builder, LHS, RHS, Name);
323 break;
324 }
325 case LLVMAlloca: {
Amaury Sechet1dcf5772016-02-09 22:50:53 +0000326 LLVMTypeRef Ty = clone_type(LLVMGetAllocatedType(Src), Ctx);
Amaury Secheta82042e2016-02-09 22:36:41 +0000327 Dst = LLVMBuildAlloca(Builder, Ty, Name);
328 break;
329 }
Amaury Sechete7e62172016-02-09 23:15:02 +0000330 case LLVMICmp: {
331 LLVMIntPredicate Pred = LLVMGetICmpPredicate(Src);
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000332 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
333 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Sechete7e62172016-02-09 23:15:02 +0000334 Dst = LLVMBuildICmp(Builder, Pred, LHS, RHS, Name);
335 break;
336 }
Amaury Secheta82042e2016-02-09 22:36:41 +0000337 case LLVMCall: {
Amaury Secheta82042e2016-02-09 22:36:41 +0000338 SmallVector<LLVMValueRef, 8> Args;
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000339 int ArgCount = LLVMGetNumOperands(Src) - 1;
Amaury Secheta82042e2016-02-09 22:36:41 +0000340 for (int i = 0; i < ArgCount; i++)
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000341 Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
342 LLVMValueRef Fn = CloneValue(LLVMGetOperand(Src, ArgCount));
Amaury Secheta82042e2016-02-09 22:36:41 +0000343 Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
344 break;
345 }
346 default:
347 break;
348 }
349
350 if (Dst == nullptr) {
351 fprintf(stderr, "%d is not a supported opcode\n", Op);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000352 exit(-1);
353 }
354
Amaury Secheta82042e2016-02-09 22:36:41 +0000355 return VMap[Src] = Dst;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000356 }
357
Amaury Secheta82042e2016-02-09 22:36:41 +0000358 LLVMBasicBlockRef DeclareBB(LLVMBasicBlockRef Src) {
359 // Check if this is something we already computed.
360 {
361 auto i = BBMap.find(Src);
362 if (i != BBMap.end()) {
363 return i->second;
364 }
365 }
366
367 const char *Name = LLVMGetBasicBlockName(Src);
368
369 LLVMValueRef V = LLVMBasicBlockAsValue(Src);
370 if (!LLVMValueIsBasicBlock(V) || LLVMValueAsBasicBlock(V) != Src)
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000371 report_fatal_error("Basic block is not a basic block");
Amaury Secheta82042e2016-02-09 22:36:41 +0000372
373 const char *VName = LLVMGetValueName(V);
374 if (Name != VName)
375 report_fatal_error("Basic block name mismatch");
376
377 LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Fun, Name);
378 return BBMap[Src] = BB;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000379 }
380
Amaury Secheta82042e2016-02-09 22:36:41 +0000381 LLVMBasicBlockRef CloneBB(LLVMBasicBlockRef Src) {
382 LLVMBasicBlockRef BB = DeclareBB(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000383
Amaury Secheta82042e2016-02-09 22:36:41 +0000384 // Make sure ordering is correct.
385 LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Src);
386 if (Prev)
387 LLVMMoveBasicBlockAfter(BB, DeclareBB(Prev));
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000388
Amaury Secheta82042e2016-02-09 22:36:41 +0000389 LLVMValueRef First = LLVMGetFirstInstruction(Src);
390 LLVMValueRef Last = LLVMGetLastInstruction(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000391
Amaury Secheta82042e2016-02-09 22:36:41 +0000392 if (First == nullptr) {
393 if (Last != nullptr) {
394 fprintf(stderr, "Has no first instruction, but last one\n");
395 exit(-1);
396 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000397
Amaury Secheta82042e2016-02-09 22:36:41 +0000398 return BB;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000399 }
400
Amaury Secheta82042e2016-02-09 22:36:41 +0000401 LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
402 LLVMPositionBuilderAtEnd(Builder, BB);
403
404 LLVMValueRef Cur = First;
405 LLVMValueRef Next = nullptr;
406 while(true) {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000407 CloneInstruction(Cur, Builder);
Amaury Secheta82042e2016-02-09 22:36:41 +0000408 Next = LLVMGetNextInstruction(Cur);
409 if (Next == nullptr) {
410 if (Cur != Last) {
411 fprintf(stderr, "Final instruction does not match Last\n");
412 exit(-1);
413 }
414
415 break;
416 }
417
418 LLVMValueRef Prev = LLVMGetPreviousInstruction(Next);
419 if (Prev != Cur) {
420 fprintf(stderr, "Next.Previous instruction is not Current\n");
421 exit(-1);
422 }
423
424 Cur = Next;
425 }
426
427 LLVMDisposeBuilder(Builder);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000428 return BB;
429 }
430
Amaury Secheta82042e2016-02-09 22:36:41 +0000431 void CloneBBs(LLVMValueRef Src) {
432 unsigned Count = LLVMCountBasicBlocks(Src);
433 if (Count == 0)
434 return;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000435
Amaury Secheta82042e2016-02-09 22:36:41 +0000436 LLVMBasicBlockRef First = LLVMGetFirstBasicBlock(Src);
437 LLVMBasicBlockRef Last = LLVMGetLastBasicBlock(Src);
438
439 LLVMBasicBlockRef Cur = First;
440 LLVMBasicBlockRef Next = nullptr;
441 while(true) {
442 CloneBB(Cur);
443 Count--;
444 Next = LLVMGetNextBasicBlock(Cur);
445 if (Next == nullptr) {
446 if (Cur != Last) {
447 fprintf(stderr, "Final basic block does not match Last\n");
448 exit(-1);
449 }
450
451 break;
452 }
453
454 LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Next);
455 if (Prev != Cur) {
456 fprintf(stderr, "Next.Previous basic bloc is not Current\n");
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000457 exit(-1);
458 }
459
Amaury Secheta82042e2016-02-09 22:36:41 +0000460 Cur = Next;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000461 }
462
Amaury Secheta82042e2016-02-09 22:36:41 +0000463 if (Count != 0) {
464 fprintf(stderr, "Basic block count does not match iterration\n");
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000465 exit(-1);
466 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000467 }
Amaury Secheta82042e2016-02-09 22:36:41 +0000468};
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000469
470static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst) {
471 unsigned Count = LLVMCountParams(Src);
472 if (Count != LLVMCountParams(Dst)) {
473 fprintf(stderr, "Parameter count mismatch\n");
474 exit(-1);
475 }
476
477 ValueMap VMap;
478 if (Count == 0)
479 return VMap;
480
481 LLVMValueRef SrcFirst = LLVMGetFirstParam(Src);
482 LLVMValueRef DstFirst = LLVMGetFirstParam(Dst);
483 LLVMValueRef SrcLast = LLVMGetLastParam(Src);
484 LLVMValueRef DstLast = LLVMGetLastParam(Dst);
485
486 LLVMValueRef SrcCur = SrcFirst;
487 LLVMValueRef DstCur = DstFirst;
488 LLVMValueRef SrcNext = nullptr;
489 LLVMValueRef DstNext = nullptr;
490 while (true) {
491 const char *Name = LLVMGetValueName(SrcCur);
492 LLVMSetValueName(DstCur, Name);
493
494 VMap[SrcCur] = DstCur;
495
496 Count--;
497 SrcNext = LLVMGetNextParam(SrcCur);
498 DstNext = LLVMGetNextParam(DstCur);
499 if (SrcNext == nullptr && DstNext == nullptr) {
500 if (SrcCur != SrcLast) {
501 fprintf(stderr, "SrcLast param does not match End\n");
502 exit(-1);
503 }
504
505 if (DstCur != DstLast) {
506 fprintf(stderr, "DstLast param does not match End\n");
507 exit(-1);
508 }
509
510 break;
511 }
512
513 if (SrcNext == nullptr) {
514 fprintf(stderr, "SrcNext was unexpectedly null\n");
515 exit(-1);
516 }
517
518 if (DstNext == nullptr) {
519 fprintf(stderr, "DstNext was unexpectedly null\n");
520 exit(-1);
521 }
522
523 LLVMValueRef SrcPrev = LLVMGetPreviousParam(SrcNext);
524 if (SrcPrev != SrcCur) {
525 fprintf(stderr, "SrcNext.Previous param is not Current\n");
526 exit(-1);
527 }
528
529 LLVMValueRef DstPrev = LLVMGetPreviousParam(DstNext);
530 if (DstPrev != DstCur) {
531 fprintf(stderr, "DstNext.Previous param is not Current\n");
532 exit(-1);
533 }
534
535 SrcCur = SrcNext;
536 DstCur = DstNext;
537 }
538
539 if (Count != 0) {
540 fprintf(stderr, "Parameter count does not match iteration\n");
541 exit(-1);
542 }
543
544 return VMap;
545}
546
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000547static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef M) {
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000548 const char *Name = LLVMGetValueName(Src);
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000549 LLVMValueRef Fun = LLVMGetNamedFunction(M, Name);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000550 if (Fun != nullptr)
551 return Fun;
552
553 LLVMTypeRef SrcTy = LLVMTypeOf(Src);
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000554 LLVMTypeRef DstTy = clone_type(SrcTy, LLVMGetModuleContext(M));
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000555 LLVMTypeRef FunTy = LLVMGetElementType(DstTy);
556
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000557 Fun = LLVMAddFunction(M, Name, FunTy);
Amaury Secheta82042e2016-02-09 22:36:41 +0000558 FunCloner FC(Src, Fun);
559 FC.CloneBBs(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000560
561 return Fun;
562}
563
564static void clone_functions(LLVMModuleRef Src, LLVMModuleRef Dst) {
565 LLVMValueRef Begin = LLVMGetFirstFunction(Src);
566 LLVMValueRef End = LLVMGetLastFunction(Src);
567
568 LLVMValueRef Cur = Begin;
569 LLVMValueRef Next = nullptr;
570 while (true) {
571 clone_function(Cur, Dst);
572 Next = LLVMGetNextFunction(Cur);
573 if (Next == nullptr) {
574 if (Cur != End) {
575 fprintf(stderr, "Last function does not match End\n");
576 exit(-1);
577 }
578
579 break;
580 }
581
582 LLVMValueRef Prev = LLVMGetPreviousFunction(Next);
583 if (Prev != Cur) {
584 fprintf(stderr, "Next.Previous function is not Current\n");
585 exit(-1);
586 }
587
588 Cur = Next;
589 }
590}
591
Benjamin Kramer9a3bd232016-02-05 13:31:14 +0000592int llvm_echo(void) {
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000593 LLVMEnablePrettyStackTrace();
594
Benjamin Kramer9a3bd232016-02-05 13:31:14 +0000595 LLVMModuleRef Src = llvm_load_module(false, true);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000596
597 LLVMContextRef Ctx = LLVMContextCreate();
598 LLVMModuleRef Dst = LLVMModuleCreateWithNameInContext("<stdin>", Ctx);
599
600 clone_functions(Src, Dst);
601 char *Str = LLVMPrintModuleToString(Dst);
602 fputs(Str, stdout);
603
604 LLVMDisposeMessage(Str);
605 LLVMDisposeModule(Dst);
606 LLVMContextDispose(Ctx);
607
608 return 0;
609}