123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955 |
- //===-- echo.cpp - tool for testing libLLVM and llvm-c API ----------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements the --echo command in llvm-c-test.
- //
- // This command uses the C API to read a module and output an exact copy of it
- // as output. It is used to check that the resulting module matches the input
- // to validate that the C API can read and write modules properly.
- //
- //===----------------------------------------------------------------------===//
- #include "llvm-c-test.h"
- #include "llvm-c/Target.h"
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/Support/ErrorHandling.h"
- #include <stdio.h>
- #include <stdlib.h>
- using namespace llvm;
- // Provide DenseMapInfo for C API opaque types.
- template<typename T>
- struct CAPIDenseMap {};
- // The default DenseMapInfo require to know about pointer alignement.
- // Because the C API uses opaques pointer types, their alignement is unknown.
- // As a result, we need to roll out our own implementation.
- template<typename T>
- struct CAPIDenseMap<T*> {
- struct CAPIDenseMapInfo {
- static inline T* getEmptyKey() {
- uintptr_t Val = static_cast<uintptr_t>(-1);
- return reinterpret_cast<T*>(Val);
- }
- static inline T* getTombstoneKey() {
- uintptr_t Val = static_cast<uintptr_t>(-2);
- return reinterpret_cast<T*>(Val);
- }
- static unsigned getHashValue(const T *PtrVal) {
- return hash_value(PtrVal);
- }
- static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
- };
- typedef DenseMap<T*, T*, CAPIDenseMapInfo> Map;
- };
- typedef CAPIDenseMap<LLVMValueRef>::Map ValueMap;
- typedef CAPIDenseMap<LLVMBasicBlockRef>::Map BasicBlockMap;
- struct TypeCloner {
- LLVMModuleRef M;
- LLVMContextRef Ctx;
- TypeCloner(LLVMModuleRef M): M(M), Ctx(LLVMGetModuleContext(M)) {}
- LLVMTypeRef Clone(LLVMValueRef Src) {
- return Clone(LLVMTypeOf(Src));
- }
- LLVMTypeRef Clone(LLVMTypeRef Src) {
- LLVMTypeKind Kind = LLVMGetTypeKind(Src);
- switch (Kind) {
- case LLVMVoidTypeKind:
- return LLVMVoidTypeInContext(Ctx);
- case LLVMHalfTypeKind:
- return LLVMHalfTypeInContext(Ctx);
- case LLVMFloatTypeKind:
- return LLVMFloatTypeInContext(Ctx);
- case LLVMDoubleTypeKind:
- return LLVMDoubleTypeInContext(Ctx);
- case LLVMX86_FP80TypeKind:
- return LLVMX86FP80TypeInContext(Ctx);
- case LLVMFP128TypeKind:
- return LLVMFP128TypeInContext(Ctx);
- case LLVMPPC_FP128TypeKind:
- return LLVMPPCFP128TypeInContext(Ctx);
- case LLVMLabelTypeKind:
- return LLVMLabelTypeInContext(Ctx);
- case LLVMIntegerTypeKind:
- return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));
- case LLVMFunctionTypeKind: {
- unsigned ParamCount = LLVMCountParamTypes(Src);
- LLVMTypeRef* Params = nullptr;
- if (ParamCount > 0) {
- Params = (LLVMTypeRef*) malloc(ParamCount * sizeof(LLVMTypeRef));
- LLVMGetParamTypes(Src, Params);
- for (unsigned i = 0; i < ParamCount; i++)
- Params[i] = Clone(Params[i]);
- }
- LLVMTypeRef FunTy = LLVMFunctionType(Clone(LLVMGetReturnType(Src)),
- Params, ParamCount,
- LLVMIsFunctionVarArg(Src));
- if (ParamCount > 0)
- free(Params);
- return FunTy;
- }
- case LLVMStructTypeKind: {
- LLVMTypeRef S = nullptr;
- const char *Name = LLVMGetStructName(Src);
- if (Name) {
- S = LLVMGetTypeByName(M, Name);
- if (S)
- return S;
- S = LLVMStructCreateNamed(Ctx, Name);
- if (LLVMIsOpaqueStruct(Src))
- return S;
- }
- unsigned EltCount = LLVMCountStructElementTypes(Src);
- SmallVector<LLVMTypeRef, 8> Elts;
- for (unsigned i = 0; i < EltCount; i++)
- Elts.push_back(Clone(LLVMStructGetTypeAtIndex(Src, i)));
- if (Name)
- LLVMStructSetBody(S, Elts.data(), EltCount, LLVMIsPackedStruct(Src));
- else
- S = LLVMStructTypeInContext(Ctx, Elts.data(), EltCount,
- LLVMIsPackedStruct(Src));
- return S;
- }
- case LLVMArrayTypeKind:
- return LLVMArrayType(
- Clone(LLVMGetElementType(Src)),
- LLVMGetArrayLength(Src)
- );
- case LLVMPointerTypeKind:
- return LLVMPointerType(
- Clone(LLVMGetElementType(Src)),
- LLVMGetPointerAddressSpace(Src)
- );
- case LLVMVectorTypeKind:
- return LLVMVectorType(
- Clone(LLVMGetElementType(Src)),
- LLVMGetVectorSize(Src)
- );
- case LLVMMetadataTypeKind:
- return LLVMMetadataTypeInContext(Ctx);
- case LLVMX86_MMXTypeKind:
- return LLVMX86MMXTypeInContext(Ctx);
- default:
- break;
- }
- fprintf(stderr, "%d is not a supported typekind\n", Kind);
- exit(-1);
- }
- };
- static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst) {
- unsigned Count = LLVMCountParams(Src);
- if (Count != LLVMCountParams(Dst))
- report_fatal_error("Parameter count mismatch");
- ValueMap VMap;
- if (Count == 0)
- return VMap;
- LLVMValueRef SrcFirst = LLVMGetFirstParam(Src);
- LLVMValueRef DstFirst = LLVMGetFirstParam(Dst);
- LLVMValueRef SrcLast = LLVMGetLastParam(Src);
- LLVMValueRef DstLast = LLVMGetLastParam(Dst);
- LLVMValueRef SrcCur = SrcFirst;
- LLVMValueRef DstCur = DstFirst;
- LLVMValueRef SrcNext = nullptr;
- LLVMValueRef DstNext = nullptr;
- while (true) {
- const char *Name = LLVMGetValueName(SrcCur);
- LLVMSetValueName(DstCur, Name);
- VMap[SrcCur] = DstCur;
- Count--;
- SrcNext = LLVMGetNextParam(SrcCur);
- DstNext = LLVMGetNextParam(DstCur);
- if (SrcNext == nullptr && DstNext == nullptr) {
- if (SrcCur != SrcLast)
- report_fatal_error("SrcLast param does not match End");
- if (DstCur != DstLast)
- report_fatal_error("DstLast param does not match End");
- break;
- }
- if (SrcNext == nullptr)
- report_fatal_error("SrcNext was unexpectedly null");
- if (DstNext == nullptr)
- report_fatal_error("DstNext was unexpectedly null");
- LLVMValueRef SrcPrev = LLVMGetPreviousParam(SrcNext);
- if (SrcPrev != SrcCur)
- report_fatal_error("SrcNext.Previous param is not Current");
- LLVMValueRef DstPrev = LLVMGetPreviousParam(DstNext);
- if (DstPrev != DstCur)
- report_fatal_error("DstNext.Previous param is not Current");
- SrcCur = SrcNext;
- DstCur = DstNext;
- }
- if (Count != 0)
- report_fatal_error("Parameter count does not match iteration");
- return VMap;
- }
- static void check_value_kind(LLVMValueRef V, LLVMValueKind K) {
- if (LLVMGetValueKind(V) != K)
- report_fatal_error("LLVMGetValueKind returned incorrect type");
- }
- static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M);
- static LLVMValueRef clone_constant(LLVMValueRef Cst, LLVMModuleRef M) {
- LLVMValueRef Ret = clone_constant_impl(Cst, M);
- check_value_kind(Ret, LLVMGetValueKind(Cst));
- return Ret;
- }
- static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
- if (!LLVMIsAConstant(Cst))
- report_fatal_error("Expected a constant");
- // Maybe it is a symbol
- if (LLVMIsAGlobalValue(Cst)) {
- const char *Name = LLVMGetValueName(Cst);
- // Try function
- if (LLVMIsAFunction(Cst)) {
- check_value_kind(Cst, LLVMFunctionValueKind);
- LLVMValueRef Dst = LLVMGetNamedFunction(M, Name);
- if (Dst)
- return Dst;
- report_fatal_error("Could not find function");
- }
- // Try global variable
- if (LLVMIsAGlobalVariable(Cst)) {
- check_value_kind(Cst, LLVMGlobalVariableValueKind);
- LLVMValueRef Dst = LLVMGetNamedGlobal(M, Name);
- if (Dst)
- return Dst;
- report_fatal_error("Could not find function");
- }
- fprintf(stderr, "Could not find @%s\n", Name);
- exit(-1);
- }
- // Try integer literal
- if (LLVMIsAConstantInt(Cst)) {
- check_value_kind(Cst, LLVMConstantIntValueKind);
- return LLVMConstInt(TypeCloner(M).Clone(Cst),
- LLVMConstIntGetZExtValue(Cst), false);
- }
- // Try zeroinitializer
- if (LLVMIsAConstantAggregateZero(Cst)) {
- check_value_kind(Cst, LLVMConstantAggregateZeroValueKind);
- return LLVMConstNull(TypeCloner(M).Clone(Cst));
- }
- // Try constant array
- if (LLVMIsAConstantArray(Cst)) {
- check_value_kind(Cst, LLVMConstantArrayValueKind);
- LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
- unsigned EltCount = LLVMGetArrayLength(Ty);
- SmallVector<LLVMValueRef, 8> Elts;
- for (unsigned i = 0; i < EltCount; i++)
- Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M));
- return LLVMConstArray(LLVMGetElementType(Ty), Elts.data(), EltCount);
- }
- // Try contant data array
- if (LLVMIsAConstantDataArray(Cst)) {
- check_value_kind(Cst, LLVMConstantDataArrayValueKind);
- LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
- unsigned EltCount = LLVMGetArrayLength(Ty);
- SmallVector<LLVMValueRef, 8> Elts;
- for (unsigned i = 0; i < EltCount; i++)
- Elts.push_back(clone_constant(LLVMGetElementAsConstant(Cst, i), M));
- return LLVMConstArray(LLVMGetElementType(Ty), Elts.data(), EltCount);
- }
- // Try constant struct
- if (LLVMIsAConstantStruct(Cst)) {
- check_value_kind(Cst, LLVMConstantStructValueKind);
- LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
- unsigned EltCount = LLVMCountStructElementTypes(Ty);
- SmallVector<LLVMValueRef, 8> Elts;
- for (unsigned i = 0; i < EltCount; i++)
- Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M));
- if (LLVMGetStructName(Ty))
- return LLVMConstNamedStruct(Ty, Elts.data(), EltCount);
- return LLVMConstStructInContext(LLVMGetModuleContext(M), Elts.data(),
- EltCount, LLVMIsPackedStruct(Ty));
- }
- // Try undef
- if (LLVMIsUndef(Cst)) {
- check_value_kind(Cst, LLVMUndefValueValueKind);
- return LLVMGetUndef(TypeCloner(M).Clone(Cst));
- }
- // Try float literal
- if (LLVMIsAConstantFP(Cst)) {
- check_value_kind(Cst, LLVMConstantFPValueKind);
- report_fatal_error("ConstantFP is not supported");
- }
- // This kind of constant is not supported
- if (!LLVMIsAConstantExpr(Cst))
- report_fatal_error("Expected a constant expression");
- // At this point, it must be a constant expression
- check_value_kind(Cst, LLVMConstantExprValueKind);
- LLVMOpcode Op = LLVMGetConstOpcode(Cst);
- switch(Op) {
- case LLVMBitCast:
- return LLVMConstBitCast(clone_constant(LLVMGetOperand(Cst, 0), M),
- TypeCloner(M).Clone(Cst));
- default:
- fprintf(stderr, "%d is not a supported opcode\n", Op);
- exit(-1);
- }
- }
- struct FunCloner {
- LLVMValueRef Fun;
- LLVMModuleRef M;
- ValueMap VMap;
- BasicBlockMap BBMap;
- FunCloner(LLVMValueRef Src, LLVMValueRef Dst): Fun(Dst),
- M(LLVMGetGlobalParent(Fun)), VMap(clone_params(Src, Dst)) {}
- LLVMTypeRef CloneType(LLVMTypeRef Src) {
- return TypeCloner(M).Clone(Src);
- }
- LLVMTypeRef CloneType(LLVMValueRef Src) {
- return TypeCloner(M).Clone(Src);
- }
- // Try to clone everything in the llvm::Value hierarchy.
- LLVMValueRef CloneValue(LLVMValueRef Src) {
- // First, the value may be constant.
- if (LLVMIsAConstant(Src))
- return clone_constant(Src, M);
- // Function argument should always be in the map already.
- auto i = VMap.find(Src);
- if (i != VMap.end())
- return i->second;
- if (!LLVMIsAInstruction(Src))
- report_fatal_error("Expected an instruction");
- auto Ctx = LLVMGetModuleContext(M);
- auto Builder = LLVMCreateBuilderInContext(Ctx);
- auto BB = DeclareBB(LLVMGetInstructionParent(Src));
- LLVMPositionBuilderAtEnd(Builder, BB);
- auto Dst = CloneInstruction(Src, Builder);
- LLVMDisposeBuilder(Builder);
- return Dst;
- }
- void CloneAttrs(LLVMValueRef Src, LLVMValueRef Dst) {
- auto Ctx = LLVMGetModuleContext(M);
- int ArgCount = LLVMGetNumArgOperands(Src);
- for (int i = LLVMAttributeReturnIndex; i <= ArgCount; i++) {
- for (unsigned k = 0, e = LLVMGetLastEnumAttributeKind(); k < e; ++k) {
- if (auto SrcA = LLVMGetCallSiteEnumAttribute(Src, i, k)) {
- auto Val = LLVMGetEnumAttributeValue(SrcA);
- auto A = LLVMCreateEnumAttribute(Ctx, k, Val);
- LLVMAddCallSiteAttribute(Dst, i, A);
- }
- }
- }
- }
- LLVMValueRef CloneInstruction(LLVMValueRef Src, LLVMBuilderRef Builder) {
- check_value_kind(Src, LLVMInstructionValueKind);
- if (!LLVMIsAInstruction(Src))
- report_fatal_error("Expected an instruction");
- const char *Name = LLVMGetValueName(Src);
- // Check if this is something we already computed.
- {
- auto i = VMap.find(Src);
- if (i != VMap.end()) {
- // If we have a hit, it means we already generated the instruction
- // as a dependancy to somethign else. We need to make sure
- // it is ordered properly.
- auto I = i->second;
- LLVMInstructionRemoveFromParent(I);
- LLVMInsertIntoBuilderWithName(Builder, I, Name);
- return I;
- }
- }
- // We tried everything, it must be an instruction
- // that hasn't been generated already.
- LLVMValueRef Dst = nullptr;
- LLVMOpcode Op = LLVMGetInstructionOpcode(Src);
- switch(Op) {
- case LLVMRet: {
- int OpCount = LLVMGetNumOperands(Src);
- if (OpCount == 0)
- Dst = LLVMBuildRetVoid(Builder);
- else
- Dst = LLVMBuildRet(Builder, CloneValue(LLVMGetOperand(Src, 0)));
- break;
- }
- case LLVMBr: {
- if (!LLVMIsConditional(Src)) {
- LLVMValueRef SrcOp = LLVMGetOperand(Src, 0);
- LLVMBasicBlockRef SrcBB = LLVMValueAsBasicBlock(SrcOp);
- Dst = LLVMBuildBr(Builder, DeclareBB(SrcBB));
- break;
- }
- LLVMValueRef Cond = LLVMGetCondition(Src);
- LLVMValueRef Else = LLVMGetOperand(Src, 1);
- LLVMBasicBlockRef ElseBB = DeclareBB(LLVMValueAsBasicBlock(Else));
- LLVMValueRef Then = LLVMGetOperand(Src, 2);
- LLVMBasicBlockRef ThenBB = DeclareBB(LLVMValueAsBasicBlock(Then));
- Dst = LLVMBuildCondBr(Builder, Cond, ThenBB, ElseBB);
- break;
- }
- case LLVMSwitch:
- case LLVMIndirectBr:
- break;
- case LLVMInvoke: {
- SmallVector<LLVMValueRef, 8> Args;
- int ArgCount = LLVMGetNumArgOperands(Src);
- for (int i = 0; i < ArgCount; i++)
- Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
- LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
- LLVMBasicBlockRef Then = DeclareBB(LLVMGetNormalDest(Src));
- LLVMBasicBlockRef Unwind = DeclareBB(LLVMGetUnwindDest(Src));
- Dst = LLVMBuildInvoke(Builder, Fn, Args.data(), ArgCount,
- Then, Unwind, Name);
- CloneAttrs(Src, Dst);
- break;
- }
- case LLVMUnreachable:
- Dst = LLVMBuildUnreachable(Builder);
- break;
- case LLVMAdd: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMSub: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildSub(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMMul: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildMul(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMUDiv: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildUDiv(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMSDiv: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildSDiv(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMURem: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildURem(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMSRem: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildSRem(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMShl: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildShl(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMLShr: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildLShr(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMAShr: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildAShr(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMAnd: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildAnd(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMOr: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildOr(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMXor: {
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildXor(Builder, LHS, RHS, Name);
- break;
- }
- case LLVMAlloca: {
- LLVMTypeRef Ty = CloneType(LLVMGetAllocatedType(Src));
- Dst = LLVMBuildAlloca(Builder, Ty, Name);
- break;
- }
- case LLVMLoad: {
- LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
- Dst = LLVMBuildLoad(Builder, Ptr, Name);
- LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
- break;
- }
- case LLVMStore: {
- LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildStore(Builder, Val, Ptr);
- LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
- break;
- }
- case LLVMGetElementPtr: {
- LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
- SmallVector<LLVMValueRef, 8> Idx;
- int NumIdx = LLVMGetNumIndices(Src);
- for (int i = 1; i <= NumIdx; i++)
- Idx.push_back(CloneValue(LLVMGetOperand(Src, i)));
- if (LLVMIsInBounds(Src))
- Dst = LLVMBuildInBoundsGEP(Builder, Ptr, Idx.data(), NumIdx, Name);
- else
- Dst = LLVMBuildGEP(Builder, Ptr, Idx.data(), NumIdx, Name);
- break;
- }
- case LLVMAtomicCmpXchg: {
- LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef Cmp = CloneValue(LLVMGetOperand(Src, 1));
- LLVMValueRef New = CloneValue(LLVMGetOperand(Src, 2));
- LLVMAtomicOrdering Succ = LLVMGetCmpXchgSuccessOrdering(Src);
- LLVMAtomicOrdering Fail = LLVMGetCmpXchgFailureOrdering(Src);
- LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src);
- Dst = LLVMBuildAtomicCmpXchg(Builder, Ptr, Cmp, New, Succ, Fail,
- SingleThread);
- } break;
- case LLVMBitCast: {
- LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 0));
- Dst = LLVMBuildBitCast(Builder, V, CloneType(Src), Name);
- break;
- }
- case LLVMICmp: {
- LLVMIntPredicate Pred = LLVMGetICmpPredicate(Src);
- LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
- Dst = LLVMBuildICmp(Builder, Pred, LHS, RHS, Name);
- break;
- }
- case LLVMPHI: {
- // We need to aggressively set things here because of loops.
- VMap[Src] = Dst = LLVMBuildPhi(Builder, CloneType(Src), Name);
- SmallVector<LLVMValueRef, 8> Values;
- SmallVector<LLVMBasicBlockRef, 8> Blocks;
- unsigned IncomingCount = LLVMCountIncoming(Src);
- for (unsigned i = 0; i < IncomingCount; ++i) {
- Blocks.push_back(DeclareBB(LLVMGetIncomingBlock(Src, i)));
- Values.push_back(CloneValue(LLVMGetIncomingValue(Src, i)));
- }
- LLVMAddIncoming(Dst, Values.data(), Blocks.data(), IncomingCount);
- return Dst;
- }
- case LLVMCall: {
- SmallVector<LLVMValueRef, 8> Args;
- int ArgCount = LLVMGetNumArgOperands(Src);
- for (int i = 0; i < ArgCount; i++)
- Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
- LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
- Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
- LLVMSetTailCall(Dst, LLVMIsTailCall(Src));
- CloneAttrs(Src, Dst);
- break;
- }
- case LLVMResume: {
- Dst = LLVMBuildResume(Builder, CloneValue(LLVMGetOperand(Src, 0)));
- break;
- }
- case LLVMLandingPad: {
- // The landing pad API is a bit screwed up for historical reasons.
- Dst = LLVMBuildLandingPad(Builder, CloneType(Src), nullptr, 0, Name);
- unsigned NumClauses = LLVMGetNumClauses(Src);
- for (unsigned i = 0; i < NumClauses; ++i)
- LLVMAddClause(Dst, CloneValue(LLVMGetClause(Src, i)));
- LLVMSetCleanup(Dst, LLVMIsCleanup(Src));
- break;
- }
- case LLVMExtractValue: {
- LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
- if (LLVMGetNumIndices(Src) != 1)
- report_fatal_error("Expected only one indice");
- auto I = LLVMGetIndices(Src)[0];
- Dst = LLVMBuildExtractValue(Builder, Agg, I, Name);
- break;
- }
- case LLVMInsertValue: {
- LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
- LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1));
- if (LLVMGetNumIndices(Src) != 1)
- report_fatal_error("Expected only one indice");
- auto I = LLVMGetIndices(Src)[0];
- Dst = LLVMBuildInsertValue(Builder, Agg, V, I, Name);
- break;
- }
- default:
- break;
- }
- if (Dst == nullptr) {
- fprintf(stderr, "%d is not a supported opcode\n", Op);
- exit(-1);
- }
- check_value_kind(Dst, LLVMInstructionValueKind);
- return VMap[Src] = Dst;
- }
- LLVMBasicBlockRef DeclareBB(LLVMBasicBlockRef Src) {
- // Check if this is something we already computed.
- {
- auto i = BBMap.find(Src);
- if (i != BBMap.end()) {
- return i->second;
- }
- }
- LLVMValueRef V = LLVMBasicBlockAsValue(Src);
- if (!LLVMValueIsBasicBlock(V) || LLVMValueAsBasicBlock(V) != Src)
- report_fatal_error("Basic block is not a basic block");
- const char *Name = LLVMGetBasicBlockName(Src);
- const char *VName = LLVMGetValueName(V);
- if (Name != VName)
- report_fatal_error("Basic block name mismatch");
- LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Fun, Name);
- return BBMap[Src] = BB;
- }
- LLVMBasicBlockRef CloneBB(LLVMBasicBlockRef Src) {
- LLVMBasicBlockRef BB = DeclareBB(Src);
- // Make sure ordering is correct.
- LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Src);
- if (Prev)
- LLVMMoveBasicBlockAfter(BB, DeclareBB(Prev));
- LLVMValueRef First = LLVMGetFirstInstruction(Src);
- LLVMValueRef Last = LLVMGetLastInstruction(Src);
- if (First == nullptr) {
- if (Last != nullptr)
- report_fatal_error("Has no first instruction, but last one");
- return BB;
- }
- auto Ctx = LLVMGetModuleContext(M);
- LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
- LLVMPositionBuilderAtEnd(Builder, BB);
- LLVMValueRef Cur = First;
- LLVMValueRef Next = nullptr;
- while(true) {
- CloneInstruction(Cur, Builder);
- Next = LLVMGetNextInstruction(Cur);
- if (Next == nullptr) {
- if (Cur != Last)
- report_fatal_error("Final instruction does not match Last");
- break;
- }
- LLVMValueRef Prev = LLVMGetPreviousInstruction(Next);
- if (Prev != Cur)
- report_fatal_error("Next.Previous instruction is not Current");
- Cur = Next;
- }
- LLVMDisposeBuilder(Builder);
- return BB;
- }
- void CloneBBs(LLVMValueRef Src) {
- unsigned Count = LLVMCountBasicBlocks(Src);
- if (Count == 0)
- return;
- LLVMBasicBlockRef First = LLVMGetFirstBasicBlock(Src);
- LLVMBasicBlockRef Last = LLVMGetLastBasicBlock(Src);
- LLVMBasicBlockRef Cur = First;
- LLVMBasicBlockRef Next = nullptr;
- while(true) {
- CloneBB(Cur);
- Count--;
- Next = LLVMGetNextBasicBlock(Cur);
- if (Next == nullptr) {
- if (Cur != Last)
- report_fatal_error("Final basic block does not match Last");
- break;
- }
- LLVMBasicBlockRef Prev = LLVMGetPreviousBasicBlock(Next);
- if (Prev != Cur)
- report_fatal_error("Next.Previous basic bloc is not Current");
- Cur = Next;
- }
- if (Count != 0)
- report_fatal_error("Basic block count does not match iterration");
- }
- };
- static void declare_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
- LLVMValueRef Begin = LLVMGetFirstGlobal(Src);
- LLVMValueRef End = LLVMGetLastGlobal(Src);
- LLVMValueRef Cur = Begin;
- LLVMValueRef Next = nullptr;
- if (!Begin) {
- if (End != nullptr)
- report_fatal_error("Range has an end but no beginning");
- goto FunDecl;
- }
- while (true) {
- const char *Name = LLVMGetValueName(Cur);
- if (LLVMGetNamedGlobal(M, Name))
- report_fatal_error("GlobalVariable already cloned");
- LLVMAddGlobal(M, LLVMGetElementType(TypeCloner(M).Clone(Cur)), Name);
- Next = LLVMGetNextGlobal(Cur);
- if (Next == nullptr) {
- if (Cur != End)
- report_fatal_error("");
- break;
- }
- LLVMValueRef Prev = LLVMGetPreviousGlobal(Next);
- if (Prev != Cur)
- report_fatal_error("Next.Previous global is not Current");
- Cur = Next;
- }
- FunDecl:
- Begin = LLVMGetFirstFunction(Src);
- End = LLVMGetLastFunction(Src);
- if (!Begin) {
- if (End != nullptr)
- report_fatal_error("Range has an end but no beginning");
- return;
- }
- auto Ctx = LLVMGetModuleContext(M);
- Cur = Begin;
- Next = nullptr;
- while (true) {
- const char *Name = LLVMGetValueName(Cur);
- if (LLVMGetNamedFunction(M, Name))
- report_fatal_error("Function already cloned");
- auto Ty = LLVMGetElementType(TypeCloner(M).Clone(Cur));
- auto F = LLVMAddFunction(M, Name, Ty);
- // Copy attributes
- for (int i = LLVMAttributeFunctionIndex, c = LLVMCountParams(F);
- i <= c; ++i) {
- for (unsigned k = 0, e = LLVMGetLastEnumAttributeKind(); k < e; ++k) {
- if (auto SrcA = LLVMGetEnumAttributeAtIndex(Cur, i, k)) {
- auto Val = LLVMGetEnumAttributeValue(SrcA);
- auto DstA = LLVMCreateEnumAttribute(Ctx, k, Val);
- LLVMAddAttributeAtIndex(F, i, DstA);
- }
- }
- }
- Next = LLVMGetNextFunction(Cur);
- if (Next == nullptr) {
- if (Cur != End)
- report_fatal_error("Last function does not match End");
- break;
- }
- LLVMValueRef Prev = LLVMGetPreviousFunction(Next);
- if (Prev != Cur)
- report_fatal_error("Next.Previous function is not Current");
- Cur = Next;
- }
- }
- static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
- LLVMValueRef Begin = LLVMGetFirstGlobal(Src);
- LLVMValueRef End = LLVMGetLastGlobal(Src);
- LLVMValueRef Cur = Begin;
- LLVMValueRef Next = nullptr;
- if (!Begin) {
- if (End != nullptr)
- report_fatal_error("Range has an end but no beginning");
- goto FunClone;
- }
- while (true) {
- const char *Name = LLVMGetValueName(Cur);
- LLVMValueRef G = LLVMGetNamedGlobal(M, Name);
- if (!G)
- report_fatal_error("GlobalVariable must have been declared already");
- if (auto I = LLVMGetInitializer(Cur))
- LLVMSetInitializer(G, clone_constant(I, M));
- LLVMSetGlobalConstant(G, LLVMIsGlobalConstant(Cur));
- LLVMSetThreadLocal(G, LLVMIsThreadLocal(Cur));
- LLVMSetExternallyInitialized(G, LLVMIsExternallyInitialized(Cur));
- LLVMSetLinkage(G, LLVMGetLinkage(Cur));
- LLVMSetSection(G, LLVMGetSection(Cur));
- LLVMSetVisibility(G, LLVMGetVisibility(Cur));
- LLVMSetUnnamedAddr(G, LLVMHasUnnamedAddr(Cur));
- LLVMSetAlignment(G, LLVMGetAlignment(Cur));
- Next = LLVMGetNextGlobal(Cur);
- if (Next == nullptr) {
- if (Cur != End)
- report_fatal_error("");
- break;
- }
- LLVMValueRef Prev = LLVMGetPreviousGlobal(Next);
- if (Prev != Cur)
- report_fatal_error("Next.Previous global is not Current");
- Cur = Next;
- }
- FunClone:
- Begin = LLVMGetFirstFunction(Src);
- End = LLVMGetLastFunction(Src);
- if (!Begin) {
- if (End != nullptr)
- report_fatal_error("Range has an end but no beginning");
- return;
- }
- Cur = Begin;
- Next = nullptr;
- while (true) {
- const char *Name = LLVMGetValueName(Cur);
- LLVMValueRef Fun = LLVMGetNamedFunction(M, Name);
- if (!Fun)
- report_fatal_error("Function must have been declared already");
- if (LLVMHasPersonalityFn(Cur)) {
- const char *FName = LLVMGetValueName(LLVMGetPersonalityFn(Cur));
- LLVMValueRef P = LLVMGetNamedFunction(M, FName);
- if (!P)
- report_fatal_error("Could not find personality function");
- LLVMSetPersonalityFn(Fun, P);
- }
- FunCloner FC(Cur, Fun);
- FC.CloneBBs(Cur);
- Next = LLVMGetNextFunction(Cur);
- if (Next == nullptr) {
- if (Cur != End)
- report_fatal_error("Last function does not match End");
- break;
- }
- LLVMValueRef Prev = LLVMGetPreviousFunction(Next);
- if (Prev != Cur)
- report_fatal_error("Next.Previous function is not Current");
- Cur = Next;
- }
- }
- int llvm_echo(void) {
- LLVMEnablePrettyStackTrace();
- LLVMModuleRef Src = llvm_load_module(false, true);
- size_t SourceFileLen;
- const char *SourceFileName = LLVMGetSourceFileName(Src, &SourceFileLen);
- size_t ModuleIdentLen;
- const char *ModuleName = LLVMGetModuleIdentifier(Src, &ModuleIdentLen);
- LLVMContextRef Ctx = LLVMContextCreate();
- LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleName, Ctx);
- LLVMSetSourceFileName(M, SourceFileName, SourceFileLen);
- LLVMSetModuleIdentifier(M, ModuleName, ModuleIdentLen);
- LLVMSetTarget(M, LLVMGetTarget(Src));
- LLVMSetModuleDataLayout(M, LLVMGetModuleDataLayout(Src));
- if (strcmp(LLVMGetDataLayoutStr(M), LLVMGetDataLayoutStr(Src)))
- report_fatal_error("Inconsistent DataLayout string representation");
- declare_symbols(Src, M);
- clone_symbols(Src, M);
- char *Str = LLVMPrintModuleToString(M);
- fputs(Str, stdout);
- LLVMDisposeMessage(Str);
- LLVMDisposeModule(M);
- LLVMContextDispose(Ctx);
- return 0;
- }
|