blob: 0b929fd4677d7a8d21d899a5dc0d223f8076ff9c [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"
20
21#include <stdio.h>
22#include <stdlib.h>
23
24using namespace llvm;
25
26// Provide DenseMapInfo for C API opaque types.
27template<typename T>
28struct CAPIDenseMap {};
29
30// The default DenseMapInfo require to know about pointer alignement.
31// Because the C API uses opaques pointer types, their alignement is unknown.
32// As a result, we need to roll out our own implementation.
33template<typename T>
34struct CAPIDenseMap<T*> {
35 struct CAPIDenseMapInfo {
36 static inline T* getEmptyKey() {
37 uintptr_t Val = static_cast<uintptr_t>(-1);
38 return reinterpret_cast<T*>(Val);
39 }
40 static inline T* getTombstoneKey() {
41 uintptr_t Val = static_cast<uintptr_t>(-2);
42 return reinterpret_cast<T*>(Val);
43 }
44 static unsigned getHashValue(const T *PtrVal) {
45 return hash_value(PtrVal);
46 }
47 static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
48 };
49
50 typedef DenseMap<T*, T*, CAPIDenseMapInfo> Map;
51};
52
53typedef CAPIDenseMap<LLVMValueRef>::Map ValueMap;
54
55static LLVMTypeRef clone_type(LLVMTypeRef Src, LLVMContextRef Ctx) {
56 LLVMTypeKind Kind = LLVMGetTypeKind(Src);
57 switch (Kind) {
58 case LLVMVoidTypeKind:
59 return LLVMVoidTypeInContext(Ctx);
60 case LLVMHalfTypeKind:
61 return LLVMHalfTypeInContext(Ctx);
62 case LLVMFloatTypeKind:
63 return LLVMFloatTypeInContext(Ctx);
64 case LLVMDoubleTypeKind:
65 return LLVMDoubleTypeInContext(Ctx);
66 case LLVMX86_FP80TypeKind:
67 return LLVMX86FP80TypeInContext(Ctx);
68 case LLVMFP128TypeKind:
69 return LLVMFP128TypeInContext(Ctx);
70 case LLVMPPC_FP128TypeKind:
71 return LLVMPPCFP128TypeInContext(Ctx);
72 case LLVMLabelTypeKind:
73 return LLVMLabelTypeInContext(Ctx);
74 case LLVMIntegerTypeKind:
75 return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));
76 case LLVMFunctionTypeKind: {
77 unsigned ParamCount = LLVMCountParamTypes(Src);
78 LLVMTypeRef* Params = nullptr;
79 if (ParamCount > 0) {
80 Params = (LLVMTypeRef*) malloc(ParamCount * sizeof(LLVMTypeRef));
81 LLVMGetParamTypes(Src, Params);
82 for (unsigned i = 0; i < ParamCount; i++) {
83 Params[i] = clone_type(Params[i], Ctx);
84 }
85 }
86
87 LLVMTypeRef FunTy = LLVMFunctionType(
88 clone_type(LLVMGetReturnType(Src), Ctx),
89 Params, ParamCount,
90 LLVMIsFunctionVarArg(Src)
91 );
92
93 if (ParamCount > 0)
94 free(Params);
95
96 return FunTy;
97 }
98 case LLVMStructTypeKind:
99 break;
100 case LLVMArrayTypeKind:
101 return LLVMArrayType(
102 clone_type(LLVMGetElementType(Src), Ctx),
103 LLVMGetArrayLength(Src)
104 );
105 case LLVMPointerTypeKind:
106 return LLVMPointerType(
107 clone_type(LLVMGetElementType(Src), Ctx),
108 LLVMGetPointerAddressSpace(Src)
109 );
110 case LLVMVectorTypeKind:
111 return LLVMVectorType(
112 clone_type(LLVMGetElementType(Src), Ctx),
113 LLVMGetVectorSize(Src)
114 );
115 case LLVMMetadataTypeKind:
116 break;
117 case LLVMX86_MMXTypeKind:
118 return LLVMX86MMXTypeInContext(Ctx);
119 default:
120 break;
121 }
122
123 fprintf(stderr, "%d is not a supported typekind\n", Kind);
124 exit(-1);
125}
126
127static LLVMValueRef clone_literal(LLVMValueRef Src, LLVMContextRef Ctx) {
128 LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
129
130 LLVMTypeKind Kind = LLVMGetTypeKind(Ty);
131 switch (Kind) {
132 case LLVMIntegerTypeKind:
133 return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);
134 default:
135 break;
136 }
137
138 fprintf(stderr, "%d is not a supported constant typekind\n", Kind);
139 exit(-1);
140}
141
142static LLVMModuleRef get_module(LLVMBuilderRef Builder) {
143 LLVMBasicBlockRef BB = LLVMGetInsertBlock(Builder);
144 LLVMValueRef Fn = LLVMGetBasicBlockParent(BB);
145 return LLVMGetGlobalParent(Fn);
146}
147
148// Try to clone everything in the llvm::Value hierarchy.
149static LLVMValueRef clone_value(LLVMValueRef Src, LLVMBuilderRef Builder, ValueMap &VMap) {
150 const char *Name = LLVMGetValueName(Src);
151
152 // First, the value may be constant.
153 if (LLVMIsAConstant(Src)) {
154 LLVMModuleRef M = get_module(Builder);
155
156 // Maybe it is a symbol
157 if (LLVMIsAGlobalValue(Src)) {
158 // Try function
159 LLVMValueRef Dst = LLVMGetNamedFunction(M, Name);
160 if (Dst != nullptr)
161 return Dst;
162
163 // Try global variable
164 Dst = LLVMGetNamedGlobal(M, Name);
165 if (Dst != nullptr)
166 return Dst;
167
168 fprintf(stderr, "Could not find @%s\n", Name);
169 exit(-1);
170 }
171
172 // Try literal
173 LLVMContextRef Ctx = LLVMGetModuleContext(M);
174 return clone_literal(Src, Ctx);
175 }
176
177 // Try undef
178 if (LLVMIsUndef(Src)) {
179 LLVMContextRef Ctx = LLVMGetModuleContext(get_module(Builder));
180 LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
181 return LLVMGetUndef(Ty);
182 }
183
184 // Check if this is something we already computed.
185 {
186 auto i = VMap.find(Src);
187 if (i != VMap.end())
188 return i->second;
189 }
190
191 // We tried everything, it must be an instruction
192 // that hasn't been generated already.
193 LLVMValueRef Dst = nullptr;
194
195 LLVMOpcode Op = LLVMGetInstructionOpcode(Src);
196 switch(Op) {
197 case LLVMRet: {
198 int OpCount = LLVMGetNumOperands(Src);
199 if (OpCount == 0)
200 Dst = LLVMBuildRetVoid(Builder);
201 else
202 Dst = LLVMBuildRet(Builder, clone_value(LLVMGetOperand(Src, 0),
203 Builder, VMap));
204 break;
205 }
206 case LLVMBr:
207 case LLVMSwitch:
208 case LLVMIndirectBr:
209 case LLVMInvoke:
210 case LLVMUnreachable:
211 break;
212 case LLVMAdd: {
213 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
214 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
215 Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);
216 break;
217 }
Amaury Sechetb6df4352016-02-05 01:27:11 +0000218 case LLVMSub: {
219 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
220 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
221 Dst = LLVMBuildSub(Builder, LHS, RHS, Name);
222 break;
223 }
224 case LLVMMul: {
225 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
226 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
227 Dst = LLVMBuildMul(Builder, LHS, RHS, Name);
228 break;
229 }
230 case LLVMUDiv: {
231 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
232 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
233 Dst = LLVMBuildUDiv(Builder, LHS, RHS, Name);
234 break;
235 }
236 case LLVMSDiv: {
237 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
238 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
239 Dst = LLVMBuildSDiv(Builder, LHS, RHS, Name);
240 break;
241 }
242 case LLVMURem: {
243 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
244 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
245 Dst = LLVMBuildURem(Builder, LHS, RHS, Name);
246 break;
247 }
248 case LLVMSRem: {
249 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
250 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
251 Dst = LLVMBuildSRem(Builder, LHS, RHS, Name);
252 break;
253 }
254 case LLVMShl: {
255 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
256 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
257 Dst = LLVMBuildShl(Builder, LHS, RHS, Name);
258 break;
259 }
260 case LLVMLShr: {
261 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
262 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
263 Dst = LLVMBuildLShr(Builder, LHS, RHS, Name);
264 break;
265 }
266 case LLVMAShr: {
267 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
268 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
269 Dst = LLVMBuildAShr(Builder, LHS, RHS, Name);
270 break;
271 }
272 case LLVMAnd: {
273 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
274 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
275 Dst = LLVMBuildAnd(Builder, LHS, RHS, Name);
276 break;
277 }
278 case LLVMOr: {
279 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
280 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
281 Dst = LLVMBuildOr(Builder, LHS, RHS, Name);
282 break;
283 }
284 case LLVMXor: {
285 LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);
286 LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);
287 Dst = LLVMBuildXor(Builder, LHS, RHS, Name);
288 break;
289 }
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000290 case LLVMAlloca: {
291 LLVMTypeRef Ty = LLVMGetElementType(LLVMTypeOf(Src));
292 Dst = LLVMBuildAlloca(Builder, Ty, Name);
293 break;
294 }
295 case LLVMCall: {
296 int ArgCount = LLVMGetNumOperands(Src) - 1;
297 SmallVector<LLVMValueRef, 8> Args;
298 for (int i = 0; i < ArgCount; i++)
299 Args.push_back(clone_value(LLVMGetOperand(Src, i), Builder, VMap));
300 LLVMValueRef Fn = clone_value(LLVMGetOperand(Src, ArgCount), Builder, VMap);
301 Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
302 break;
303 }
304 default:
305 break;
306 }
307
308 if (Dst == nullptr) {
309 fprintf(stderr, "%d is not a supported opcode\n", Op);
310 exit(-1);
311 }
312
313 return VMap[Src] = Dst;
314}
315
316static LLVMBasicBlockRef clone_bb(LLVMBasicBlockRef Src, LLVMValueRef Dst, ValueMap &VMap) {
317 LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Dst, "");
318
319 LLVMValueRef First = LLVMGetFirstInstruction(Src);
320 LLVMValueRef Last = LLVMGetLastInstruction(Src);
321
322 if (First == nullptr) {
323 if (Last != nullptr) {
324 fprintf(stderr, "Has no first instruction, but last one\n");
325 exit(-1);
326 }
327
328 return BB;
329 }
330
331 LLVMContextRef Ctx = LLVMGetModuleContext(LLVMGetGlobalParent(Dst));
332 LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
333 LLVMPositionBuilderAtEnd(Builder, BB);
334
335 LLVMValueRef Cur = First;
336 LLVMValueRef Next = nullptr;
337 while(true) {
338 clone_value(Cur, Builder, VMap);
339 Next = LLVMGetNextInstruction(Cur);
340 if (Next == nullptr) {
341 if (Cur != Last) {
342 fprintf(stderr, "Final instruction does not match Last\n");
343 exit(-1);
344 }
345
346 break;
347 }
348
349 LLVMValueRef Prev = LLVMGetPreviousInstruction(Next);
350 if (Prev != Cur) {
351 fprintf(stderr, "Next.Previous instruction is not Current\n");
352 exit(-1);
353 }
354
355 Cur = Next;
356 }
357
358 LLVMDisposeBuilder(Builder);
359 return BB;
360}
361
362static void clone_bbs(LLVMValueRef Src, LLVMValueRef Dst, ValueMap &VMap) {
363 unsigned Count = LLVMCountBasicBlocks(Src);
364 if (Count == 0)
365 return;
366
367 LLVMBasicBlockRef First = LLVMGetFirstBasicBlock(Src);
368 LLVMBasicBlockRef Last = LLVMGetLastBasicBlock(Src);
369
370 LLVMBasicBlockRef Cur = First;
371 LLVMBasicBlockRef Next = nullptr;
372 while(true) {
373 clone_bb(Cur, Dst, VMap);
374 Count--;
375 Next = LLVMGetNextBasicBlock(Cur);
376 if (Next == nullptr) {
377 if (Cur != Last) {
378 fprintf(stderr, "Final basic block does not match Last\n");
379 exit(-1);
380 }
381
382 break;
383 }
384
385 LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Next);
386 if (Prev != Cur) {
387 fprintf(stderr, "Next.Previous basic bloc is not Current\n");
388 exit(-1);
389 }
390
391 Cur = Next;
392 }
393
394 if (Count != 0) {
395 fprintf(stderr, "Basic block count does not match iterration\n");
396 exit(-1);
397 }
398}
399
400static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst) {
401 unsigned Count = LLVMCountParams(Src);
402 if (Count != LLVMCountParams(Dst)) {
403 fprintf(stderr, "Parameter count mismatch\n");
404 exit(-1);
405 }
406
407 ValueMap VMap;
408 if (Count == 0)
409 return VMap;
410
411 LLVMValueRef SrcFirst = LLVMGetFirstParam(Src);
412 LLVMValueRef DstFirst = LLVMGetFirstParam(Dst);
413 LLVMValueRef SrcLast = LLVMGetLastParam(Src);
414 LLVMValueRef DstLast = LLVMGetLastParam(Dst);
415
416 LLVMValueRef SrcCur = SrcFirst;
417 LLVMValueRef DstCur = DstFirst;
418 LLVMValueRef SrcNext = nullptr;
419 LLVMValueRef DstNext = nullptr;
420 while (true) {
421 const char *Name = LLVMGetValueName(SrcCur);
422 LLVMSetValueName(DstCur, Name);
423
424 VMap[SrcCur] = DstCur;
425
426 Count--;
427 SrcNext = LLVMGetNextParam(SrcCur);
428 DstNext = LLVMGetNextParam(DstCur);
429 if (SrcNext == nullptr && DstNext == nullptr) {
430 if (SrcCur != SrcLast) {
431 fprintf(stderr, "SrcLast param does not match End\n");
432 exit(-1);
433 }
434
435 if (DstCur != DstLast) {
436 fprintf(stderr, "DstLast param does not match End\n");
437 exit(-1);
438 }
439
440 break;
441 }
442
443 if (SrcNext == nullptr) {
444 fprintf(stderr, "SrcNext was unexpectedly null\n");
445 exit(-1);
446 }
447
448 if (DstNext == nullptr) {
449 fprintf(stderr, "DstNext was unexpectedly null\n");
450 exit(-1);
451 }
452
453 LLVMValueRef SrcPrev = LLVMGetPreviousParam(SrcNext);
454 if (SrcPrev != SrcCur) {
455 fprintf(stderr, "SrcNext.Previous param is not Current\n");
456 exit(-1);
457 }
458
459 LLVMValueRef DstPrev = LLVMGetPreviousParam(DstNext);
460 if (DstPrev != DstCur) {
461 fprintf(stderr, "DstNext.Previous param is not Current\n");
462 exit(-1);
463 }
464
465 SrcCur = SrcNext;
466 DstCur = DstNext;
467 }
468
469 if (Count != 0) {
470 fprintf(stderr, "Parameter count does not match iteration\n");
471 exit(-1);
472 }
473
474 return VMap;
475}
476
477static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef Dst) {
478 const char *Name = LLVMGetValueName(Src);
479 LLVMValueRef Fun = LLVMGetNamedFunction(Dst, Name);
480 if (Fun != nullptr)
481 return Fun;
482
483 LLVMTypeRef SrcTy = LLVMTypeOf(Src);
484 LLVMTypeRef DstTy = clone_type(SrcTy, LLVMGetModuleContext(Dst));
485 LLVMTypeRef FunTy = LLVMGetElementType(DstTy);
486
487 Fun = LLVMAddFunction(Dst, Name, FunTy);
488
489 ValueMap VMap = clone_params(Src, Fun);
490 clone_bbs(Src, Fun, VMap);
491
492 return Fun;
493}
494
495static void clone_functions(LLVMModuleRef Src, LLVMModuleRef Dst) {
496 LLVMValueRef Begin = LLVMGetFirstFunction(Src);
497 LLVMValueRef End = LLVMGetLastFunction(Src);
498
499 LLVMValueRef Cur = Begin;
500 LLVMValueRef Next = nullptr;
501 while (true) {
502 clone_function(Cur, Dst);
503 Next = LLVMGetNextFunction(Cur);
504 if (Next == nullptr) {
505 if (Cur != End) {
506 fprintf(stderr, "Last function does not match End\n");
507 exit(-1);
508 }
509
510 break;
511 }
512
513 LLVMValueRef Prev = LLVMGetPreviousFunction(Next);
514 if (Prev != Cur) {
515 fprintf(stderr, "Next.Previous function is not Current\n");
516 exit(-1);
517 }
518
519 Cur = Next;
520 }
521}
522
Benjamin Kramer9a3bd232016-02-05 13:31:14 +0000523int llvm_echo(void) {
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000524 LLVMEnablePrettyStackTrace();
525
Benjamin Kramer9a3bd232016-02-05 13:31:14 +0000526 LLVMModuleRef Src = llvm_load_module(false, true);
Amaury Sechete8ea7d82016-02-04 23:26:19 +0000527
528 LLVMContextRef Ctx = LLVMContextCreate();
529 LLVMModuleRef Dst = LLVMModuleCreateWithNameInContext("<stdin>", Ctx);
530
531 clone_functions(Src, Dst);
532 char *Str = LLVMPrintModuleToString(Dst);
533 fputs(Str, stdout);
534
535 LLVMDisposeMessage(Str);
536 LLVMDisposeModule(Dst);
537 LLVMContextDispose(Ctx);
538
539 return 0;
540}