959 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			959 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- 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:
 | 
						|
        break;
 | 
						|
      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 agressively 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 begining");
 | 
						|
    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 begining");
 | 
						|
    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 begining");
 | 
						|
    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 begining");
 | 
						|
    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 Len;
 | 
						|
  const char *ModuleName = LLVMGetModuleIdentifier(Src, &Len);
 | 
						|
  LLVMContextRef Ctx = LLVMContextCreate();
 | 
						|
  LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleName, Ctx);
 | 
						|
 | 
						|
  // This whole switcharound is done because the C API has no way to
 | 
						|
  // set the source_filename
 | 
						|
  LLVMSetModuleIdentifier(M, "", 0);
 | 
						|
  LLVMGetModuleIdentifier(M, &Len);
 | 
						|
  if (Len != 0)
 | 
						|
      report_fatal_error("LLVM{Set,Get}ModuleIdentifier failed");
 | 
						|
  LLVMSetModuleIdentifier(M, ModuleName, strlen(ModuleName));
 | 
						|
 | 
						|
  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;
 | 
						|
}
 |