<div dir="ltr">fputs(Str, cout) ends up making files with DOS line endings on Windows, causing the test to fail on the 'diff' step. I'll add -w to make it pass. I'm assuming you don't care about whitespace changes?</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Feb 4, 2016 at 3:26 PM, Amaury Sechet via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: deadalnix<br>
Date: Thu Feb 4 17:26:19 2016<br>
New Revision: 259844<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=259844&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=259844&view=rev</a><br>
Log:<br>
Improve testing for the C API<br>
<br>
Summary:<br>
This basically add an echo test case in C. The support is limited right now, but full support would just be too much to review at once.<br>
<br>
The echo test case simply get a module as input and try to output the same exact module. This allow to check the both reading and writing API are working as expected.<br>
<br>
I want to improve this test over time to support more and more of the API, in order to improve coverage (coverage is quite poor right now).<br>
<br>
Test Plan: Run the test.<br>
<br>
Reviewers: chandlerc, bogner<br>
<br>
Subscribers: llvm-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D10725" rel="noreferrer" target="_blank">http://reviews.llvm.org/D10725</a><br>
<br>
Added:<br>
llvm/trunk/test/Bindings/llvm-c/echo.ll<br>
llvm/trunk/tools/llvm-c-test/echo.cpp<br>
Modified:<br>
llvm/trunk/tools/llvm-c-test/CMakeLists.txt<br>
llvm/trunk/tools/llvm-c-test/calc.c<br>
llvm/trunk/tools/llvm-c-test/llvm-c-test.h<br>
llvm/trunk/tools/llvm-c-test/main.c<br>
llvm/trunk/tools/llvm-c-test/metadata.c<br>
llvm/trunk/tools/llvm-c-test/module.c<br>
llvm/trunk/tools/llvm-c-test/object.c<br>
<br>
Added: llvm/trunk/test/Bindings/llvm-c/echo.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bindings/llvm-c/echo.ll?rev=259844&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bindings/llvm-c/echo.ll?rev=259844&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bindings/llvm-c/echo.ll (added)<br>
+++ llvm/trunk/test/Bindings/llvm-c/echo.ll Thu Feb 4 17:26:19 2016<br>
@@ -0,0 +1,32 @@<br>
+; RUN: llvm-as < %s | llvm-dis > %t.orig<br>
+; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo<br>
+; RUN: diff %t.orig %t.echo<br>
+<br>
+declare void @decl()<br>
+<br>
+; TODO: label, struct and metadata types<br>
+define void @types() {<br>
+ %1 = alloca half<br>
+ %2 = alloca float<br>
+ %3 = alloca double<br>
+ %4 = alloca x86_fp80<br>
+ %5 = alloca fp128<br>
+ %6 = alloca ppc_fp128<br>
+ %7 = alloca i7<br>
+ %8 = alloca void (i1)*<br>
+ %9 = alloca [3 x i22]<br>
+ %10 = alloca i328 addrspace(5)*<br>
+ %11 = alloca <5 x i23*><br>
+ %12 = alloca x86_mmx<br>
+ ret void<br>
+}<br>
+<br>
+define i32 @add(i32 %a, i32 %b) {<br>
+ %1 = add i32 %a, %b<br>
+ ret i32 %1<br>
+}<br>
+<br>
+define i32 @call() {<br>
+ %1 = call i32 @add(i32 23, i32 19)<br>
+ ret i32 %1<br>
+}<br>
<br>
Modified: llvm/trunk/tools/llvm-c-test/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/CMakeLists.txt?rev=259844&r1=259843&r2=259844&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/CMakeLists.txt?rev=259844&r1=259843&r2=259844&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-c-test/CMakeLists.txt (original)<br>
+++ llvm/trunk/tools/llvm-c-test/CMakeLists.txt Thu Feb 4 17:26:19 2016<br>
@@ -37,6 +37,7 @@ endif ()<br>
add_llvm_tool(llvm-c-test<br>
calc.c<br>
disassemble.c<br>
+ echo.cpp<br>
helpers.c<br>
include-all.c<br>
main.c<br>
<br>
Modified: llvm/trunk/tools/llvm-c-test/calc.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/calc.c?rev=259844&r1=259843&r2=259844&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/calc.c?rev=259844&r1=259843&r2=259844&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-c-test/calc.c (original)<br>
+++ llvm/trunk/tools/llvm-c-test/calc.c Thu Feb 4 17:26:19 2016<br>
@@ -14,7 +14,6 @@<br>
\*===----------------------------------------------------------------------===*/<br>
<br>
#include "llvm-c-test.h"<br>
-#include "llvm-c/Core.h"<br>
#include <stdio.h><br>
#include <stdlib.h><br>
#include <string.h><br>
<br>
Added: llvm/trunk/tools/llvm-c-test/echo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/echo.cpp?rev=259844&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/echo.cpp?rev=259844&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-c-test/echo.cpp (added)<br>
+++ llvm/trunk/tools/llvm-c-test/echo.cpp Thu Feb 4 17:26:19 2016<br>
@@ -0,0 +1,468 @@<br>
+//===-- echo.cpp - tool for testing libLLVM and llvm-c API ----------------===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file implements the --echo commands in llvm-c-test.<br>
+//<br>
+// This command uses the C API to read a module and output an exact copy of it<br>
+// as output. It is used to check that the resulting module matches the input<br>
+// to validate that the C API can read and write modules properly.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm-c-test.h"<br>
+#include "llvm/ADT/DenseMap.h"<br>
+<br>
+#include <stdio.h><br>
+#include <stdlib.h><br>
+<br>
+using namespace llvm;<br>
+<br>
+// Provide DenseMapInfo for C API opaque types.<br>
+template<typename T><br>
+struct CAPIDenseMap {};<br>
+<br>
+// The default DenseMapInfo require to know about pointer alignement.<br>
+// Because the C API uses opaques pointer types, their alignement is unknown.<br>
+// As a result, we need to roll out our own implementation.<br>
+template<typename T><br>
+struct CAPIDenseMap<T*> {<br>
+ struct CAPIDenseMapInfo {<br>
+ static inline T* getEmptyKey() {<br>
+ uintptr_t Val = static_cast<uintptr_t>(-1);<br>
+ return reinterpret_cast<T*>(Val);<br>
+ }<br>
+ static inline T* getTombstoneKey() {<br>
+ uintptr_t Val = static_cast<uintptr_t>(-2);<br>
+ return reinterpret_cast<T*>(Val);<br>
+ }<br>
+ static unsigned getHashValue(const T *PtrVal) {<br>
+ return hash_value(PtrVal);<br>
+ }<br>
+ static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }<br>
+ };<br>
+<br>
+ typedef DenseMap<T*, T*, CAPIDenseMapInfo> Map;<br>
+};<br>
+<br>
+typedef CAPIDenseMap<LLVMValueRef>::Map ValueMap;<br>
+<br>
+static LLVMTypeRef clone_type(LLVMTypeRef Src, LLVMContextRef Ctx) {<br>
+ LLVMTypeKind Kind = LLVMGetTypeKind(Src);<br>
+ switch (Kind) {<br>
+ case LLVMVoidTypeKind:<br>
+ return LLVMVoidTypeInContext(Ctx);<br>
+ case LLVMHalfTypeKind:<br>
+ return LLVMHalfTypeInContext(Ctx);<br>
+ case LLVMFloatTypeKind:<br>
+ return LLVMFloatTypeInContext(Ctx);<br>
+ case LLVMDoubleTypeKind:<br>
+ return LLVMDoubleTypeInContext(Ctx);<br>
+ case LLVMX86_FP80TypeKind:<br>
+ return LLVMX86FP80TypeInContext(Ctx);<br>
+ case LLVMFP128TypeKind:<br>
+ return LLVMFP128TypeInContext(Ctx);<br>
+ case LLVMPPC_FP128TypeKind:<br>
+ return LLVMPPCFP128TypeInContext(Ctx);<br>
+ case LLVMLabelTypeKind:<br>
+ return LLVMLabelTypeInContext(Ctx);<br>
+ case LLVMIntegerTypeKind:<br>
+ return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));<br>
+ case LLVMFunctionTypeKind: {<br>
+ unsigned ParamCount = LLVMCountParamTypes(Src);<br>
+ LLVMTypeRef* Params = nullptr;<br>
+ if (ParamCount > 0) {<br>
+ Params = (LLVMTypeRef*) malloc(ParamCount * sizeof(LLVMTypeRef));<br>
+ LLVMGetParamTypes(Src, Params);<br>
+ for (unsigned i = 0; i < ParamCount; i++) {<br>
+ Params[i] = clone_type(Params[i], Ctx);<br>
+ }<br>
+ }<br>
+<br>
+ LLVMTypeRef FunTy = LLVMFunctionType(<br>
+ clone_type(LLVMGetReturnType(Src), Ctx),<br>
+ Params, ParamCount,<br>
+ LLVMIsFunctionVarArg(Src)<br>
+ );<br>
+<br>
+ if (ParamCount > 0)<br>
+ free(Params);<br>
+<br>
+ return FunTy;<br>
+ }<br>
+ case LLVMStructTypeKind:<br>
+ break;<br>
+ case LLVMArrayTypeKind:<br>
+ return LLVMArrayType(<br>
+ clone_type(LLVMGetElementType(Src), Ctx),<br>
+ LLVMGetArrayLength(Src)<br>
+ );<br>
+ case LLVMPointerTypeKind:<br>
+ return LLVMPointerType(<br>
+ clone_type(LLVMGetElementType(Src), Ctx),<br>
+ LLVMGetPointerAddressSpace(Src)<br>
+ );<br>
+ case LLVMVectorTypeKind:<br>
+ return LLVMVectorType(<br>
+ clone_type(LLVMGetElementType(Src), Ctx),<br>
+ LLVMGetVectorSize(Src)<br>
+ );<br>
+ case LLVMMetadataTypeKind:<br>
+ break;<br>
+ case LLVMX86_MMXTypeKind:<br>
+ return LLVMX86MMXTypeInContext(Ctx);<br>
+ default:<br>
+ break;<br>
+ }<br>
+<br>
+ fprintf(stderr, "%d is not a supported typekind\n", Kind);<br>
+ exit(-1);<br>
+}<br>
+<br>
+static LLVMValueRef clone_literal(LLVMValueRef Src, LLVMContextRef Ctx) {<br>
+ LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);<br>
+<br>
+ LLVMTypeKind Kind = LLVMGetTypeKind(Ty);<br>
+ switch (Kind) {<br>
+ case LLVMIntegerTypeKind:<br>
+ return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);<br>
+ default:<br>
+ break;<br>
+ }<br>
+<br>
+ fprintf(stderr, "%d is not a supported constant typekind\n", Kind);<br>
+ exit(-1);<br>
+}<br>
+<br>
+static LLVMModuleRef get_module(LLVMBuilderRef Builder) {<br>
+ LLVMBasicBlockRef BB = LLVMGetInsertBlock(Builder);<br>
+ LLVMValueRef Fn = LLVMGetBasicBlockParent(BB);<br>
+ return LLVMGetGlobalParent(Fn);<br>
+}<br>
+<br>
+// Try to clone everything in the llvm::Value hierarchy.<br>
+static LLVMValueRef clone_value(LLVMValueRef Src, LLVMBuilderRef Builder, ValueMap &VMap) {<br>
+ const char *Name = LLVMGetValueName(Src);<br>
+<br>
+ // First, the value may be constant.<br>
+ if (LLVMIsAConstant(Src)) {<br>
+ LLVMModuleRef M = get_module(Builder);<br>
+<br>
+ // Maybe it is a symbol<br>
+ if (LLVMIsAGlobalValue(Src)) {<br>
+ // Try function<br>
+ LLVMValueRef Dst = LLVMGetNamedFunction(M, Name);<br>
+ if (Dst != nullptr)<br>
+ return Dst;<br>
+<br>
+ // Try global variable<br>
+ Dst = LLVMGetNamedGlobal(M, Name);<br>
+ if (Dst != nullptr)<br>
+ return Dst;<br>
+<br>
+ fprintf(stderr, "Could not find @%s\n", Name);<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ // Try literal<br>
+ LLVMContextRef Ctx = LLVMGetModuleContext(M);<br>
+ return clone_literal(Src, Ctx);<br>
+ }<br>
+<br>
+ // Try undef<br>
+ if (LLVMIsUndef(Src)) {<br>
+ LLVMContextRef Ctx = LLVMGetModuleContext(get_module(Builder));<br>
+ LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);<br>
+ return LLVMGetUndef(Ty);<br>
+ }<br>
+<br>
+ // Check if this is something we already computed.<br>
+ {<br>
+ auto i = VMap.find(Src);<br>
+ if (i != VMap.end())<br>
+ return i->second;<br>
+ }<br>
+<br>
+ // We tried everything, it must be an instruction<br>
+ // that hasn't been generated already.<br>
+ LLVMValueRef Dst = nullptr;<br>
+<br>
+ LLVMOpcode Op = LLVMGetInstructionOpcode(Src);<br>
+ switch(Op) {<br>
+ case LLVMRet: {<br>
+ int OpCount = LLVMGetNumOperands(Src);<br>
+ if (OpCount == 0)<br>
+ Dst = LLVMBuildRetVoid(Builder);<br>
+ else<br>
+ Dst = LLVMBuildRet(Builder, clone_value(LLVMGetOperand(Src, 0),<br>
+ Builder, VMap));<br>
+ break;<br>
+ }<br>
+ case LLVMBr:<br>
+ case LLVMSwitch:<br>
+ case LLVMIndirectBr:<br>
+ case LLVMInvoke:<br>
+ case LLVMUnreachable:<br>
+ break;<br>
+ case LLVMAdd: {<br>
+ LLVMValueRef LHS = clone_value(LLVMGetOperand(Src, 0), Builder, VMap);<br>
+ LLVMValueRef RHS = clone_value(LLVMGetOperand(Src, 1), Builder, VMap);<br>
+ Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);<br>
+ break;<br>
+ }<br>
+ case LLVMAlloca: {<br>
+ LLVMTypeRef Ty = LLVMGetElementType(LLVMTypeOf(Src));<br>
+ Dst = LLVMBuildAlloca(Builder, Ty, Name);<br>
+ break;<br>
+ }<br>
+ case LLVMCall: {<br>
+ int ArgCount = LLVMGetNumOperands(Src) - 1;<br>
+ SmallVector<LLVMValueRef, 8> Args;<br>
+ for (int i = 0; i < ArgCount; i++)<br>
+ Args.push_back(clone_value(LLVMGetOperand(Src, i), Builder, VMap));<br>
+ LLVMValueRef Fn = clone_value(LLVMGetOperand(Src, ArgCount), Builder, VMap);<br>
+ Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);<br>
+ break;<br>
+ }<br>
+ default:<br>
+ break;<br>
+ }<br>
+<br>
+ if (Dst == nullptr) {<br>
+ fprintf(stderr, "%d is not a supported opcode\n", Op);<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ return VMap[Src] = Dst;<br>
+}<br>
+<br>
+static LLVMBasicBlockRef clone_bb(LLVMBasicBlockRef Src, LLVMValueRef Dst, ValueMap &VMap) {<br>
+ LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Dst, "");<br>
+<br>
+ LLVMValueRef First = LLVMGetFirstInstruction(Src);<br>
+ LLVMValueRef Last = LLVMGetLastInstruction(Src);<br>
+<br>
+ if (First == nullptr) {<br>
+ if (Last != nullptr) {<br>
+ fprintf(stderr, "Has no first instruction, but last one\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ return BB;<br>
+ }<br>
+<br>
+ LLVMContextRef Ctx = LLVMGetModuleContext(LLVMGetGlobalParent(Dst));<br>
+ LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);<br>
+ LLVMPositionBuilderAtEnd(Builder, BB);<br>
+<br>
+ LLVMValueRef Cur = First;<br>
+ LLVMValueRef Next = nullptr;<br>
+ while(true) {<br>
+ clone_value(Cur, Builder, VMap);<br>
+ Next = LLVMGetNextInstruction(Cur);<br>
+ if (Next == nullptr) {<br>
+ if (Cur != Last) {<br>
+ fprintf(stderr, "Final instruction does not match Last\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ break;<br>
+ }<br>
+<br>
+ LLVMValueRef Prev = LLVMGetPreviousInstruction(Next);<br>
+ if (Prev != Cur) {<br>
+ fprintf(stderr, "Next.Previous instruction is not Current\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ Cur = Next;<br>
+ }<br>
+<br>
+ LLVMDisposeBuilder(Builder);<br>
+ return BB;<br>
+}<br>
+<br>
+static void clone_bbs(LLVMValueRef Src, LLVMValueRef Dst, ValueMap &VMap) {<br>
+ unsigned Count = LLVMCountBasicBlocks(Src);<br>
+ if (Count == 0)<br>
+ return;<br>
+<br>
+ LLVMBasicBlockRef First = LLVMGetFirstBasicBlock(Src);<br>
+ LLVMBasicBlockRef Last = LLVMGetLastBasicBlock(Src);<br>
+<br>
+ LLVMBasicBlockRef Cur = First;<br>
+ LLVMBasicBlockRef Next = nullptr;<br>
+ while(true) {<br>
+ clone_bb(Cur, Dst, VMap);<br>
+ Count--;<br>
+ Next = LLVMGetNextBasicBlock(Cur);<br>
+ if (Next == nullptr) {<br>
+ if (Cur != Last) {<br>
+ fprintf(stderr, "Final basic block does not match Last\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ break;<br>
+ }<br>
+<br>
+ LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Next);<br>
+ if (Prev != Cur) {<br>
+ fprintf(stderr, "Next.Previous basic bloc is not Current\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ Cur = Next;<br>
+ }<br>
+<br>
+ if (Count != 0) {<br>
+ fprintf(stderr, "Basic block count does not match iterration\n");<br>
+ exit(-1);<br>
+ }<br>
+}<br>
+<br>
+static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst) {<br>
+ unsigned Count = LLVMCountParams(Src);<br>
+ if (Count != LLVMCountParams(Dst)) {<br>
+ fprintf(stderr, "Parameter count mismatch\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ ValueMap VMap;<br>
+ if (Count == 0)<br>
+ return VMap;<br>
+<br>
+ LLVMValueRef SrcFirst = LLVMGetFirstParam(Src);<br>
+ LLVMValueRef DstFirst = LLVMGetFirstParam(Dst);<br>
+ LLVMValueRef SrcLast = LLVMGetLastParam(Src);<br>
+ LLVMValueRef DstLast = LLVMGetLastParam(Dst);<br>
+<br>
+ LLVMValueRef SrcCur = SrcFirst;<br>
+ LLVMValueRef DstCur = DstFirst;<br>
+ LLVMValueRef SrcNext = nullptr;<br>
+ LLVMValueRef DstNext = nullptr;<br>
+ while (true) {<br>
+ const char *Name = LLVMGetValueName(SrcCur);<br>
+ LLVMSetValueName(DstCur, Name);<br>
+<br>
+ VMap[SrcCur] = DstCur;<br>
+<br>
+ Count--;<br>
+ SrcNext = LLVMGetNextParam(SrcCur);<br>
+ DstNext = LLVMGetNextParam(DstCur);<br>
+ if (SrcNext == nullptr && DstNext == nullptr) {<br>
+ if (SrcCur != SrcLast) {<br>
+ fprintf(stderr, "SrcLast param does not match End\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ if (DstCur != DstLast) {<br>
+ fprintf(stderr, "DstLast param does not match End\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ break;<br>
+ }<br>
+<br>
+ if (SrcNext == nullptr) {<br>
+ fprintf(stderr, "SrcNext was unexpectedly null\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ if (DstNext == nullptr) {<br>
+ fprintf(stderr, "DstNext was unexpectedly null\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ LLVMValueRef SrcPrev = LLVMGetPreviousParam(SrcNext);<br>
+ if (SrcPrev != SrcCur) {<br>
+ fprintf(stderr, "SrcNext.Previous param is not Current\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ LLVMValueRef DstPrev = LLVMGetPreviousParam(DstNext);<br>
+ if (DstPrev != DstCur) {<br>
+ fprintf(stderr, "DstNext.Previous param is not Current\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ SrcCur = SrcNext;<br>
+ DstCur = DstNext;<br>
+ }<br>
+<br>
+ if (Count != 0) {<br>
+ fprintf(stderr, "Parameter count does not match iteration\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ return VMap;<br>
+}<br>
+<br>
+static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef Dst) {<br>
+ const char *Name = LLVMGetValueName(Src);<br>
+ LLVMValueRef Fun = LLVMGetNamedFunction(Dst, Name);<br>
+ if (Fun != nullptr)<br>
+ return Fun;<br>
+<br>
+ LLVMTypeRef SrcTy = LLVMTypeOf(Src);<br>
+ LLVMTypeRef DstTy = clone_type(SrcTy, LLVMGetModuleContext(Dst));<br>
+ LLVMTypeRef FunTy = LLVMGetElementType(DstTy);<br>
+<br>
+ Fun = LLVMAddFunction(Dst, Name, FunTy);<br>
+<br>
+ ValueMap VMap = clone_params(Src, Fun);<br>
+ clone_bbs(Src, Fun, VMap);<br>
+<br>
+ return Fun;<br>
+}<br>
+<br>
+static void clone_functions(LLVMModuleRef Src, LLVMModuleRef Dst) {<br>
+ LLVMValueRef Begin = LLVMGetFirstFunction(Src);<br>
+ LLVMValueRef End = LLVMGetLastFunction(Src);<br>
+<br>
+ LLVMValueRef Cur = Begin;<br>
+ LLVMValueRef Next = nullptr;<br>
+ while (true) {<br>
+ clone_function(Cur, Dst);<br>
+ Next = LLVMGetNextFunction(Cur);<br>
+ if (Next == nullptr) {<br>
+ if (Cur != End) {<br>
+ fprintf(stderr, "Last function does not match End\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ break;<br>
+ }<br>
+<br>
+ LLVMValueRef Prev = LLVMGetPreviousFunction(Next);<br>
+ if (Prev != Cur) {<br>
+ fprintf(stderr, "Next.Previous function is not Current\n");<br>
+ exit(-1);<br>
+ }<br>
+<br>
+ Cur = Next;<br>
+ }<br>
+}<br>
+<br>
+int echo(void) {<br>
+ LLVMEnablePrettyStackTrace();<br>
+<br>
+ LLVMModuleRef Src = load_module(false, true);<br>
+<br>
+ LLVMContextRef Ctx = LLVMContextCreate();<br>
+ LLVMModuleRef Dst = LLVMModuleCreateWithNameInContext("<stdin>", Ctx);<br>
+<br>
+ clone_functions(Src, Dst);<br>
+ char *Str = LLVMPrintModuleToString(Dst);<br>
+ fputs(Str, stdout);<br>
+<br>
+ LLVMDisposeMessage(Str);<br>
+ LLVMDisposeModule(Dst);<br>
+ LLVMContextDispose(Ctx);<br>
+<br>
+ return 0;<br>
+}<br>
<br>
Modified: llvm/trunk/tools/llvm-c-test/llvm-c-test.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/llvm-c-test.h?rev=259844&r1=259843&r2=259844&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/llvm-c-test.h?rev=259844&r1=259843&r2=259844&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-c-test/llvm-c-test.h (original)<br>
+++ llvm/trunk/tools/llvm-c-test/llvm-c-test.h Thu Feb 4 17:26:19 2016<br>
@@ -14,11 +14,17 @@<br>
#define LLVM_C_TEST_H<br>
<br>
#include <stdbool.h><br>
+#include "llvm-c/Core.h"<br>
+<br>
+#ifdef __cplusplus<br>
+extern "C" {<br>
+#endif<br>
<br>
// helpers.c<br>
void tokenize_stdin(void (*cb)(char **tokens, int ntokens));<br>
<br>
// module.c<br>
+LLVMModuleRef load_module(bool Lazy, bool New);<br>
int module_dump(bool Lazy, bool New);<br>
int module_list_functions(void);<br>
int module_list_globals(void);<br>
@@ -40,4 +46,11 @@ int object_list_symbols(void);<br>
// targets.c<br>
int targets_list(void);<br>
<br>
+// echo.c<br>
+int echo(void);<br>
+<br>
+#ifdef __cplusplus<br>
+}<br>
+#endif /* !defined(__cplusplus) */<br>
+<br>
#endif<br>
<br>
Modified: llvm/trunk/tools/llvm-c-test/main.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/main.c?rev=259844&r1=259843&r2=259844&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/main.c?rev=259844&r1=259843&r2=259844&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-c-test/main.c (original)<br>
+++ llvm/trunk/tools/llvm-c-test/main.c Thu Feb 4 17:26:19 2016<br>
@@ -13,7 +13,6 @@<br>
<br>
#include "llvm-c-test.h"<br>
#include "llvm-c/BitReader.h"<br>
-#include "llvm-c/Core.h"<br>
#include <stdio.h><br>
#include <stdlib.h><br>
#include <string.h><br>
@@ -47,6 +46,9 @@ static void print_usage(void) {<br>
fprintf(stderr, " Read lines of triple, hex ascii machine code from stdin "<br>
"- print disassembly\n\n");<br>
fprintf(stderr, " * --calc\n");<br>
+ fprintf(stderr, " * --echo\n");<br>
+ fprintf(stderr,<br>
+ " Read object file form stdin - and print it back out\n\n");<br>
fprintf(<br>
stderr,<br>
" Read lines of name, rpn from stdin - print generated module\n\n");<br>
@@ -83,6 +85,8 @@ int main(int argc, char **argv) {<br>
return add_named_metadata_operand();<br>
} else if (argc == 2 && !strcmp(argv[1], "--set-metadata")) {<br>
return set_metadata();<br>
+ } else if (argc == 2 && !strcmp(argv[1], "--echo")) {<br>
+ return echo();<br>
} else {<br>
print_usage();<br>
}<br>
<br>
Modified: llvm/trunk/tools/llvm-c-test/metadata.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/metadata.c?rev=259844&r1=259843&r2=259844&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/metadata.c?rev=259844&r1=259843&r2=259844&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-c-test/metadata.c (original)<br>
+++ llvm/trunk/tools/llvm-c-test/metadata.c Thu Feb 4 17:26:19 2016<br>
@@ -13,7 +13,6 @@<br>
\*===----------------------------------------------------------------------===*/<br>
<br>
#include "llvm-c-test.h"<br>
-#include "llvm-c/Core.h"<br>
<br>
int add_named_metadata_operand(void) {<br>
LLVMModuleRef m = LLVMModuleCreateWithName("Mod");<br>
<br>
Modified: llvm/trunk/tools/llvm-c-test/module.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/module.c?rev=259844&r1=259843&r2=259844&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/module.c?rev=259844&r1=259843&r2=259844&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-c-test/module.c (original)<br>
+++ llvm/trunk/tools/llvm-c-test/module.c Thu Feb 4 17:26:19 2016<br>
@@ -14,7 +14,6 @@<br>
<br>
#include "llvm-c-test.h"<br>
#include "llvm-c/BitReader.h"<br>
-#include "llvm-c/Core.h"<br>
#include <stdio.h><br>
#include <stdlib.h><br>
#include <string.h><br>
@@ -26,7 +25,7 @@ static void diagnosticHandler(LLVMDiagno<br>
exit(1);<br>
}<br>
<br>
-static LLVMModuleRef load_module(bool Lazy, bool New) {<br>
+LLVMModuleRef load_module(bool Lazy, bool New) {<br>
LLVMMemoryBufferRef MB;<br>
LLVMModuleRef M;<br>
char *msg = NULL;<br>
<br>
Modified: llvm/trunk/tools/llvm-c-test/object.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/object.c?rev=259844&r1=259843&r2=259844&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/object.c?rev=259844&r1=259843&r2=259844&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-c-test/object.c (original)<br>
+++ llvm/trunk/tools/llvm-c-test/object.c Thu Feb 4 17:26:19 2016<br>
@@ -13,7 +13,6 @@<br>
\*===----------------------------------------------------------------------===*/<br>
<br>
#include "llvm-c-test.h"<br>
-#include "llvm-c/Core.h"<br>
#include "llvm-c/Object.h"<br>
#include <stdio.h><br>
#include <stdlib.h><br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>