blob: 47f366c2f8a3870fb101741f9e91f9c4e57e645e [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
Amaury Sechetaad93532016-02-10 00:38:50 +000057struct 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;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000100 }
Amaury Sechetaad93532016-02-10 00:38:50 +0000101 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 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000112
Amaury Sechetaad93532016-02-10 00:38:50 +0000113 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;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000145 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000146
Amaury Sechetaad93532016-02-10 00:38:50 +0000147 fprintf(stderr, "%d is not a supported typekind\n", Kind);
148 exit(-1);
149 }
150};
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000151
Amaury Secheta82042e2016-02-09 22:36:41 +0000152static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000153
Amaury Secheta82042e2016-02-09 22:36:41 +0000154struct FunCloner {
155 LLVMValueRef Fun;
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000156 LLVMModuleRef M;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000157
Amaury Secheta82042e2016-02-09 22:36:41 +0000158 ValueMap VMap;
159 BasicBlockMap BBMap;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000160
Amaury Sechetaad93532016-02-10 00:38:50 +0000161 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 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000171
Amaury Secheta82042e2016-02-09 22:36:41 +0000172 // Try to clone everything in the llvm::Value hierarchy.
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000173 LLVMValueRef CloneValue(LLVMValueRef Src) {
Amaury Secheta82042e2016-02-09 22:36:41 +0000174 const char *Name = LLVMGetValueName(Src);
175
176 // First, the value may be constant.
177 if (LLVMIsAConstant(Src)) {
Amaury Secheta82042e2016-02-09 22:36:41 +0000178 // Maybe it is a symbol
179 if (LLVMIsAGlobalValue(Src)) {
180 // Try function
181 LLVMValueRef Dst = LLVMGetNamedFunction(M, Name);
182 if (Dst != nullptr)
183 return Dst;
184
185 // Try global variable
186 Dst = LLVMGetNamedGlobal(M, Name);
187 if (Dst != nullptr)
188 return Dst;
189
190 fprintf(stderr, "Could not find @%s\n", Name);
191 exit(-1);
192 }
193
194 // Try literal
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000195 if (LLVMIsAConstantInt(Src)) {
Amaury Sechetaad93532016-02-10 00:38:50 +0000196 LLVMTypeRef Ty = CloneType(Src);
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000197 return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);
198 }
199
200 // Try undef
201 if (LLVMIsUndef(Src))
Amaury Sechetaad93532016-02-10 00:38:50 +0000202 return LLVMGetUndef(CloneType(Src));
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000203
204 // This kind of constant is not supported.
205 report_fatal_error("Unsupported contant type");
Amaury Secheta82042e2016-02-09 22:36:41 +0000206 }
207
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000208 // Function argument should always be in the map already.
209 if (LLVMIsAArgument(Src)) {
210 auto i = VMap.find(Src);
211 if (i != VMap.end())
212 return i->second;
Amaury Secheta82042e2016-02-09 22:36:41 +0000213 }
214
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000215 if (LLVMIsAInstruction(Src)) {
Amaury Sechetaad93532016-02-10 00:38:50 +0000216 auto Ctx = LLVMGetModuleContext(M);
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000217 auto Builder = LLVMCreateBuilderInContext(Ctx);
218 auto BB = DeclareBB(LLVMGetInstructionParent(Src));
219 LLVMPositionBuilderAtEnd(Builder, BB);
220 auto Dst = CloneInstruction(Src, Builder);
221 LLVMDisposeBuilder(Builder);
222 return Dst;
223 }
224
225 fprintf(stderr, "Could not determine the type of %s\n", Name);
226 exit(-1);
227 }
228
229 LLVMValueRef CloneInstruction(LLVMValueRef Src, LLVMBuilderRef Builder) {
230 const char *Name = LLVMGetValueName(Src);
231 if (!LLVMIsAInstruction(Src))
232 report_fatal_error("Expected an instruction");
233
Amaury Secheta82042e2016-02-09 22:36:41 +0000234 // Check if this is something we already computed.
235 {
236 auto i = VMap.find(Src);
237 if (i != VMap.end())
238 return i->second;
239 }
240
241 // We tried everything, it must be an instruction
242 // that hasn't been generated already.
243 LLVMValueRef Dst = nullptr;
244
245 LLVMOpcode Op = LLVMGetInstructionOpcode(Src);
246 switch(Op) {
247 case LLVMRet: {
248 int OpCount = LLVMGetNumOperands(Src);
249 if (OpCount == 0)
250 Dst = LLVMBuildRetVoid(Builder);
251 else
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000252 Dst = LLVMBuildRet(Builder, CloneValue(LLVMGetOperand(Src, 0)));
Amaury Secheta82042e2016-02-09 22:36:41 +0000253 break;
254 }
255 case LLVMBr: {
Amaury Sechete7e62172016-02-09 23:15:02 +0000256 if (!LLVMIsConditional(Src)) {
257 LLVMValueRef SrcOp = LLVMGetOperand(Src, 0);
258 LLVMBasicBlockRef SrcBB = LLVMValueAsBasicBlock(SrcOp);
259 Dst = LLVMBuildBr(Builder, DeclareBB(SrcBB));
260 break;
261 }
262
263 LLVMValueRef Cond = LLVMGetCondition(Src);
264 LLVMValueRef Else = LLVMGetOperand(Src, 1);
265 LLVMBasicBlockRef ElseBB = DeclareBB(LLVMValueAsBasicBlock(Else));
266 LLVMValueRef Then = LLVMGetOperand(Src, 2);
267 LLVMBasicBlockRef ThenBB = DeclareBB(LLVMValueAsBasicBlock(Then));
268 Dst = LLVMBuildCondBr(Builder, Cond, ThenBB, ElseBB);
Amaury Secheta82042e2016-02-09 22:36:41 +0000269 break;
270 }
271 case LLVMSwitch:
272 case LLVMIndirectBr:
273 case LLVMInvoke:
274 break;
275 case LLVMUnreachable:
276 Dst = LLVMBuildUnreachable(Builder);
277 break;
278 case LLVMAdd: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000279 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
280 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000281 Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);
282 break;
283 }
284 case LLVMSub: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000285 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
286 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000287 Dst = LLVMBuildSub(Builder, LHS, RHS, Name);
288 break;
289 }
290 case LLVMMul: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000291 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
292 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000293 Dst = LLVMBuildMul(Builder, LHS, RHS, Name);
294 break;
295 }
296 case LLVMUDiv: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000297 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
298 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000299 Dst = LLVMBuildUDiv(Builder, LHS, RHS, Name);
300 break;
301 }
302 case LLVMSDiv: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000303 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
304 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000305 Dst = LLVMBuildSDiv(Builder, LHS, RHS, Name);
306 break;
307 }
308 case LLVMURem: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000309 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
310 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000311 Dst = LLVMBuildURem(Builder, LHS, RHS, Name);
312 break;
313 }
314 case LLVMSRem: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000315 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
316 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000317 Dst = LLVMBuildSRem(Builder, LHS, RHS, Name);
318 break;
319 }
320 case LLVMShl: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000321 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
322 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000323 Dst = LLVMBuildShl(Builder, LHS, RHS, Name);
324 break;
325 }
326 case LLVMLShr: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000327 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
328 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000329 Dst = LLVMBuildLShr(Builder, LHS, RHS, Name);
330 break;
331 }
332 case LLVMAShr: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000333 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
334 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000335 Dst = LLVMBuildAShr(Builder, LHS, RHS, Name);
336 break;
337 }
338 case LLVMAnd: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000339 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
340 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000341 Dst = LLVMBuildAnd(Builder, LHS, RHS, Name);
342 break;
343 }
344 case LLVMOr: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000345 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
346 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000347 Dst = LLVMBuildOr(Builder, LHS, RHS, Name);
348 break;
349 }
350 case LLVMXor: {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000351 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
352 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Secheta82042e2016-02-09 22:36:41 +0000353 Dst = LLVMBuildXor(Builder, LHS, RHS, Name);
354 break;
355 }
356 case LLVMAlloca: {
Amaury Sechetaad93532016-02-10 00:38:50 +0000357 LLVMTypeRef Ty = CloneType(LLVMGetAllocatedType(Src));
Amaury Secheta82042e2016-02-09 22:36:41 +0000358 Dst = LLVMBuildAlloca(Builder, Ty, Name);
359 break;
360 }
Amaury Sechete7e62172016-02-09 23:15:02 +0000361 case LLVMICmp: {
362 LLVMIntPredicate Pred = LLVMGetICmpPredicate(Src);
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000363 LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
364 LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
Amaury Sechete7e62172016-02-09 23:15:02 +0000365 Dst = LLVMBuildICmp(Builder, Pred, LHS, RHS, Name);
366 break;
367 }
Amaury Secheta82042e2016-02-09 22:36:41 +0000368 case LLVMCall: {
Amaury Secheta82042e2016-02-09 22:36:41 +0000369 SmallVector<LLVMValueRef, 8> Args;
Amaury Sechet5c7b3af2016-02-10 00:09:37 +0000370 int ArgCount = LLVMGetNumArgOperands(Src);
Amaury Secheta82042e2016-02-09 22:36:41 +0000371 for (int i = 0; i < ArgCount; i++)
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000372 Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
Amaury Sechet5c7b3af2016-02-10 00:09:37 +0000373 LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
Amaury Secheta82042e2016-02-09 22:36:41 +0000374 Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
375 break;
376 }
Amaury Sechetaad93532016-02-10 00:38:50 +0000377 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 }
Amaury Secheta82042e2016-02-09 22:36:41 +0000394 default:
395 break;
396 }
397
398 if (Dst == nullptr) {
399 fprintf(stderr, "%d is not a supported opcode\n", Op);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000400 exit(-1);
401 }
402
Amaury Secheta82042e2016-02-09 22:36:41 +0000403 return VMap[Src] = Dst;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000404 }
405
Amaury Secheta82042e2016-02-09 22:36:41 +0000406 LLVMBasicBlockRef DeclareBB(LLVMBasicBlockRef Src) {
407 // Check if this is something we already computed.
408 {
409 auto i = BBMap.find(Src);
410 if (i != BBMap.end()) {
411 return i->second;
412 }
413 }
414
415 const char *Name = LLVMGetBasicBlockName(Src);
416
417 LLVMValueRef V = LLVMBasicBlockAsValue(Src);
418 if (!LLVMValueIsBasicBlock(V) || LLVMValueAsBasicBlock(V) != Src)
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000419 report_fatal_error("Basic block is not a basic block");
Amaury Secheta82042e2016-02-09 22:36:41 +0000420
421 const char *VName = LLVMGetValueName(V);
422 if (Name != VName)
423 report_fatal_error("Basic block name mismatch");
424
425 LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Fun, Name);
426 return BBMap[Src] = BB;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000427 }
428
Amaury Secheta82042e2016-02-09 22:36:41 +0000429 LLVMBasicBlockRef CloneBB(LLVMBasicBlockRef Src) {
430 LLVMBasicBlockRef BB = DeclareBB(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000431
Amaury Secheta82042e2016-02-09 22:36:41 +0000432 // Make sure ordering is correct.
433 LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Src);
434 if (Prev)
435 LLVMMoveBasicBlockAfter(BB, DeclareBB(Prev));
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000436
Amaury Secheta82042e2016-02-09 22:36:41 +0000437 LLVMValueRef First = LLVMGetFirstInstruction(Src);
438 LLVMValueRef Last = LLVMGetLastInstruction(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000439
Amaury Secheta82042e2016-02-09 22:36:41 +0000440 if (First == nullptr) {
441 if (Last != nullptr) {
442 fprintf(stderr, "Has no first instruction, but last one\n");
443 exit(-1);
444 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000445
Amaury Secheta82042e2016-02-09 22:36:41 +0000446 return BB;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000447 }
448
Amaury Sechetaad93532016-02-10 00:38:50 +0000449 auto Ctx = LLVMGetModuleContext(M);
Amaury Secheta82042e2016-02-09 22:36:41 +0000450 LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
451 LLVMPositionBuilderAtEnd(Builder, BB);
452
453 LLVMValueRef Cur = First;
454 LLVMValueRef Next = nullptr;
455 while(true) {
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000456 CloneInstruction(Cur, Builder);
Amaury Secheta82042e2016-02-09 22:36:41 +0000457 Next = LLVMGetNextInstruction(Cur);
458 if (Next == nullptr) {
459 if (Cur != Last) {
460 fprintf(stderr, "Final instruction does not match Last\n");
461 exit(-1);
462 }
463
464 break;
465 }
466
467 LLVMValueRef Prev = LLVMGetPreviousInstruction(Next);
468 if (Prev != Cur) {
469 fprintf(stderr, "Next.Previous instruction is not Current\n");
470 exit(-1);
471 }
472
473 Cur = Next;
474 }
475
476 LLVMDisposeBuilder(Builder);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000477 return BB;
478 }
479
Amaury Secheta82042e2016-02-09 22:36:41 +0000480 void CloneBBs(LLVMValueRef Src) {
481 unsigned Count = LLVMCountBasicBlocks(Src);
482 if (Count == 0)
483 return;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000484
Amaury Secheta82042e2016-02-09 22:36:41 +0000485 LLVMBasicBlockRef First = LLVMGetFirstBasicBlock(Src);
486 LLVMBasicBlockRef Last = LLVMGetLastBasicBlock(Src);
487
488 LLVMBasicBlockRef Cur = First;
489 LLVMBasicBlockRef Next = nullptr;
490 while(true) {
491 CloneBB(Cur);
492 Count--;
493 Next = LLVMGetNextBasicBlock(Cur);
494 if (Next == nullptr) {
495 if (Cur != Last) {
496 fprintf(stderr, "Final basic block does not match Last\n");
497 exit(-1);
498 }
499
500 break;
501 }
502
503 LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Next);
504 if (Prev != Cur) {
505 fprintf(stderr, "Next.Previous basic bloc is not Current\n");
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000506 exit(-1);
507 }
508
Amaury Secheta82042e2016-02-09 22:36:41 +0000509 Cur = Next;
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000510 }
511
Amaury Secheta82042e2016-02-09 22:36:41 +0000512 if (Count != 0) {
513 fprintf(stderr, "Basic block count does not match iterration\n");
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000514 exit(-1);
515 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000516 }
Amaury Secheta82042e2016-02-09 22:36:41 +0000517};
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000518
519static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst) {
520 unsigned Count = LLVMCountParams(Src);
521 if (Count != LLVMCountParams(Dst)) {
522 fprintf(stderr, "Parameter count mismatch\n");
523 exit(-1);
524 }
525
526 ValueMap VMap;
527 if (Count == 0)
528 return VMap;
529
530 LLVMValueRef SrcFirst = LLVMGetFirstParam(Src);
531 LLVMValueRef DstFirst = LLVMGetFirstParam(Dst);
532 LLVMValueRef SrcLast = LLVMGetLastParam(Src);
533 LLVMValueRef DstLast = LLVMGetLastParam(Dst);
534
535 LLVMValueRef SrcCur = SrcFirst;
536 LLVMValueRef DstCur = DstFirst;
537 LLVMValueRef SrcNext = nullptr;
538 LLVMValueRef DstNext = nullptr;
539 while (true) {
540 const char *Name = LLVMGetValueName(SrcCur);
541 LLVMSetValueName(DstCur, Name);
542
543 VMap[SrcCur] = DstCur;
544
545 Count--;
546 SrcNext = LLVMGetNextParam(SrcCur);
547 DstNext = LLVMGetNextParam(DstCur);
548 if (SrcNext == nullptr && DstNext == nullptr) {
549 if (SrcCur != SrcLast) {
550 fprintf(stderr, "SrcLast param does not match End\n");
551 exit(-1);
552 }
553
554 if (DstCur != DstLast) {
555 fprintf(stderr, "DstLast param does not match End\n");
556 exit(-1);
557 }
558
559 break;
560 }
561
562 if (SrcNext == nullptr) {
563 fprintf(stderr, "SrcNext was unexpectedly null\n");
564 exit(-1);
565 }
566
567 if (DstNext == nullptr) {
568 fprintf(stderr, "DstNext was unexpectedly null\n");
569 exit(-1);
570 }
571
572 LLVMValueRef SrcPrev = LLVMGetPreviousParam(SrcNext);
573 if (SrcPrev != SrcCur) {
574 fprintf(stderr, "SrcNext.Previous param is not Current\n");
575 exit(-1);
576 }
577
578 LLVMValueRef DstPrev = LLVMGetPreviousParam(DstNext);
579 if (DstPrev != DstCur) {
580 fprintf(stderr, "DstNext.Previous param is not Current\n");
581 exit(-1);
582 }
583
584 SrcCur = SrcNext;
585 DstCur = DstNext;
586 }
587
588 if (Count != 0) {
589 fprintf(stderr, "Parameter count does not match iteration\n");
590 exit(-1);
591 }
592
593 return VMap;
594}
595
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000596static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef M) {
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000597 const char *Name = LLVMGetValueName(Src);
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000598 LLVMValueRef Fun = LLVMGetNamedFunction(M, Name);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000599 if (Fun != nullptr)
600 return Fun;
601
Amaury Sechetaad93532016-02-10 00:38:50 +0000602 LLVMTypeRef DstTy = TypeCloner(M).Clone(LLVMTypeOf(Src));
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000603 LLVMTypeRef FunTy = LLVMGetElementType(DstTy);
604
Amaury Sechet1e5d7e22016-02-09 23:41:20 +0000605 Fun = LLVMAddFunction(M, Name, FunTy);
Amaury Secheta82042e2016-02-09 22:36:41 +0000606 FunCloner FC(Src, Fun);
607 FC.CloneBBs(Src);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000608
609 return Fun;
610}
611
612static void clone_functions(LLVMModuleRef Src, LLVMModuleRef Dst) {
613 LLVMValueRef Begin = LLVMGetFirstFunction(Src);
614 LLVMValueRef End = LLVMGetLastFunction(Src);
615
616 LLVMValueRef Cur = Begin;
617 LLVMValueRef Next = nullptr;
618 while (true) {
619 clone_function(Cur, Dst);
620 Next = LLVMGetNextFunction(Cur);
621 if (Next == nullptr) {
622 if (Cur != End) {
623 fprintf(stderr, "Last function does not match End\n");
624 exit(-1);
625 }
626
627 break;
628 }
629
630 LLVMValueRef Prev = LLVMGetPreviousFunction(Next);
631 if (Prev != Cur) {
632 fprintf(stderr, "Next.Previous function is not Current\n");
633 exit(-1);
634 }
635
636 Cur = Next;
637 }
638}
639
Benjamin Kramer9a3bd232016-02-05 13:31:14 +0000640int llvm_echo(void) {
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000641 LLVMEnablePrettyStackTrace();
642
Benjamin Kramer9a3bd232016-02-05 13:31:14 +0000643 LLVMModuleRef Src = llvm_load_module(false, true);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000644
645 LLVMContextRef Ctx = LLVMContextCreate();
646 LLVMModuleRef Dst = LLVMModuleCreateWithNameInContext("<stdin>", Ctx);
647
648 clone_functions(Src, Dst);
649 char *Str = LLVMPrintModuleToString(Dst);
650 fputs(Str, stdout);
651
652 LLVMDisposeMessage(Str);
653 LLVMDisposeModule(Dst);
654 LLVMContextDispose(Ctx);
655
656 return 0;
657}