#ifndef LLVM_FPTR_STRUCT_SAFETY_ANALYSIS_H
#define LLVM_FPTR_STRUCT_SAFETY_ANALYSIS_H

//=- FuncPtrAndStrcutSafetyAnalysis.h - Func Ptr & Struct Safety Analysis --==//
//
//===----------------------------------------------------------------------===//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Copyright (c) 2015 Advanced Micro Devices, Inc.  All rights reserved.
// Developed by: Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// with the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimers.
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimers in the documentation
// and/or other materials provided with the distribution.
// Neither the names of Advanced Micro Devices, Inc., nor the names of its
// contributors may be used to endorse or promote products derived from this
// Software without specific prior written permission.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
// THE SOFTWARE.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Analysis/TypeReconstruction.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/AbstractCallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/Function.h"

using namespace llvm;

// Info holder for CallInst
class CallDetails {
public:
  CallDetails(CallInst *CI, Value *Val) : CI(CI), Val(Val) {}
  CallInst *CI;
  Value *Val;
};

// Info holder for SelectInst
class SelectDetails {
public:
  SelectDetails(SelectInst *SI, Value *Val) : SI(SI), Val(Val) {}
  SelectInst *SI;
  Value *Val;
};

// Info holder for PHINode
class PHIDetails {
public:
  PHIDetails(PHINode *PN, Value *Val) : PN(PN), Val(Val) {}
  PHINode *PN;
  Value *Val;
};

// Info holder for StoreInst
class StoreDetails {
public:
  StoreDetails(StoreInst *SI, Value *Val) : SI(SI), Val(Val) {}
  StoreInst *SI;
  Value *Val;
};

// Holding indirect calls for a particular function.
class IndirectCallerPossiblities {
public:
  IndirectCallerPossiblities(llvm::Function *F) : F(F) {}
  llvm::Function *F;
  SmallVector<CallInst *, 4> CallPossibilities;
};

// SelectInst information
class SelectInstInfo {
public:
  // Constructor
  SelectInstInfo(SelectInst *SI)
      : SI(SI), SelectValue1(nullptr), SelectValue2(nullptr) {
    SelectValue1PossibleStruct.clear();
    SelectValue2PossibleStruct.clear();
  }
  // Return first value if already identified & processed
  Value *getSelectValue1() { return SelectValue1; }
  // Return second value if already identified & processed
  Value *getSelectValue2() { return SelectValue2; }
  // Set identified & processed first value.
  void setSelectValue1(Value *V) { SelectValue1 = V; }
  // Set identified & processed second value.
  void setSelectValue2(Value *V) { SelectValue2 = V; }
  // Set first value struct type possiblities
  void setSelectValue1PossibleStruct(SmallVector<StructType *, 4> &Vec) {
    SelectValue1PossibleStruct = Vec;
  }
  // Set second value struct type possiblities
  void setSelectValue2PossibleStruct(SmallVector<StructType *, 4> &Vec) {
    SelectValue2PossibleStruct = Vec;
  }
  SelectInst *SI;
  Value *SelectValue1;
  Value *SelectValue2;
  SmallVector<StructType *, 4> SelectValue1PossibleStruct;
  SmallVector<StructType *, 4> SelectValue2PossibleStruct;
};

// StoreInst information
class StoreInstInfo {
public:
  // Constructor
  StoreInstInfo(StoreInst *SI)
      : SI(SI), StoreValue(nullptr), StorePointer(nullptr) {
    StoreValuePossibleStruct.clear();
    StorePointerPossibleStruct.clear();
  }
  // Return store value operand if already identified & processed
  Value *getStoreValue() { return StoreValue; }
  // Return store pointer operand if already identified & processed
  Value *getStorePointer() { return StorePointer; }
  // Set identified & processed store value operand.
  void setStoreValue(Value *V) { StoreValue = V; }
  // Set identified & processed store pointer operand.
  void setStorePointer(Value *V) { StorePointer = V; }
  // Set store value struct type possiblities
  void setStoreValuePossibleStruct(SmallVector<StructType *, 4> &Vec) {
    StoreValuePossibleStruct = Vec;
  }
  // Set store pointer struct type possiblities
  void setStorePointerPossibleStruct(SmallVector<StructType *, 4> &Vec) {
    StorePointerPossibleStruct = Vec;
  }
  StoreInst *SI;
  Value *StoreValue;
  Value *StorePointer;
  SmallVector<StructType *, 4> StoreValuePossibleStruct;
  SmallVector<StructType *, 4> StorePointerPossibleStruct;
};

// PHINode information
class PHINodeInfo {
public:
  // Constructor
  PHINodeInfo(PHINode *PN) : PN(PN) {
    PHIIncoming.clear();
    IncomingPossiblities.clear();
  }
  // Return already identified & processed incoming value at given index.
  Value *getInValue(unsigned Index) { return PHIIncoming[Index]; }
  // Set already identified & processed incoming value at given index.
  void setInValue(unsigned Index, Value *V) { PHIIncoming[Index] = V; }
  // Set struct type possiblities for incoming value at given index.
  void setInValuePossibleStruct(unsigned Index,
                                SmallVector<StructType *, 4> &Vec) {
    IncomingPossiblities[Index] = Vec;
  }
  // Get struct type possiblities for incoming value at given index.
  SmallVector<StructType *, 4> getInValuePossibleStruct(unsigned Index) {
    SmallVector<StructType *, 4> Dummy;
    Dummy.clear();
    if (!PHIIncoming[Index])
      return Dummy;
    return IncomingPossiblities[Index];
  }
  PHINode *PN;
  MapVector<unsigned, Value *> PHIIncoming;
  MapVector<unsigned, SmallVector<StructType *, 4>> IncomingPossiblities;
};

// CallInst information
class CallInstInfo {
public:
  // Constructor
  CallInstInfo(CallInst *CI) : CI(CI) {
    Args.clear();
    ArgsPossiblities.clear();
    UnSafeArgs.clear();
  }
  // Set already identified & processed argument value at given index.
  void setArgValue(unsigned Index, Value *V) { Args[Index] = V; }
  // Return already identified & processed argument value at given index.
  Value *getArgValue(unsigned Index) { return Args[Index]; }
  // Set struct type possiblities for argument value at given index.
  void setArgPossibleStruct(unsigned Index,
                            const SmallVector<StructType *, 4> &Vec) {
    ArgsPossiblities[Index] = Vec;
  }
  // Get struct type possiblities for argument value at given index.
  SmallVector<StructType *, 4> getArgPossibleStruct(unsigned Index) {
    SmallVector<StructType *, 4> Dummy;
    Dummy.clear();
    if (!Args[Index])
      return Dummy;
    return ArgsPossiblities[Index];
  }
  CallInst *CI;
  MapVector<unsigned, Value *> Args;
  MapVector<unsigned, SmallVector<StructType *, 4>> ArgsPossiblities;
  MapVector<Value *, bool> UnSafeArgs;
};

// MemcpyInst information
class MemCpyIntrinsicInfo {
public:
  MemCpyIntrinsicInfo(IntrinsicInst *II)
      : II(II), Source(nullptr), Destination(nullptr) {
    DestinationPossibleStruct.clear();
    SourcePossibleStruct.clear();
  }
  // Return already identified & processed source operand.
  Value *getSource() { return Source; }
  // Return already identified & processed destination operand.
  Value *getDestination() { return Destination; }
  // Set already identified & processed source operand.
  void setSource(Value *SourceV) { Source = SourceV; }
  // Set already identified & processed destination operand.
  void setDestination(Value *DestinationV) { Destination = DestinationV; }
  // Set struct type possiblities for source operand.
  void setSourcePossiblities(SmallVector<StructType *, 4> &SrcPossiblities) {
    SourcePossibleStruct = SrcPossiblities;
  }
  // Set struct type possiblities for destination operand.
  void
  setDestinationPossiblities(SmallVector<StructType *, 4> &DestPossiblities) {
    DestinationPossibleStruct = DestPossiblities;
  }
  IntrinsicInst *II;
  Value *Source;
  Value *Destination;
  SmallVector<StructType *, 4> SourcePossibleStruct;
  SmallVector<StructType *, 4> DestinationPossibleStruct;
};

// Function pointer possiblity information
class PointerPossibilitiesInfo {
public:
  PointerPossibilitiesInfo(GetElementPtrInst *Gep)
      : Gep(Gep), HasNullPtrPossiblity(false), HasUnResolvedPossiblity(false),
        StTy(nullptr), Offset(0) {
    Possibilities.clear();
    InvolvedStructType.clear();
  }
  // Set pointer with possible unresolved functions.
  void setUnResolvedPossiblity() { HasUnResolvedPossiblity = true; }
  // Return true if the PPI has any unresolved possiblity.
  bool hasUnResolvedPossiblity() { return HasUnResolvedPossiblity; }
  // Set pointer with null pointer case.
  void setNullPtrPossiblity() { HasNullPtrPossiblity = true; }
  // Set last level Struct and the field byte offset.
  void setStructAndFieldByteOffset(StructType *S, int64_t BOffset) {
    StTy = S;
    Offset = BOffset;
  }
  // Add function to the list of possiblities.
  void addFunctionPossiblity(llvm::Function *F) {
    // If already indetified the skip.
    if (isKnownPossiblity(F))
      return;
    Possibilities.push_back(F);
  }
  // Check for known possiblity.
  bool isKnownPossiblity(llvm::Function *F) {
    for (llvm::Function *PossibleF : Possibilities)
      if (PossibleF == F)
        return true;
    return false;
  }
  // Dump the pointer possiblity info.
  void dump() {
    dbgs() << "GEP:: " << *Gep << "\n";
    dbgs() << "   StructTy: " << StTy->getName() << "\n";
    dbgs() << "   Offset: " << Offset << "\n";
    dbgs() << "   HasNullPtrPossiblity: " << HasNullPtrPossiblity << "\n";
    dbgs() << "   HasUnResolvedPossiblity: " << HasUnResolvedPossiblity << "\n";
    dbgs() << "   Possiblities::\n";
    for (llvm::Function *F : Possibilities)
      dbgs() << "       - " << F->getName() << "\n";
    dbgs() << "\n";
  }

  GetElementPtrInst *Gep;
  bool HasNullPtrPossiblity;
  bool HasUnResolvedPossiblity;
  StructType *StTy;
  int64_t Offset;
  SmallVector<llvm::Function *, 4> Possibilities;
  SmallVector<StructType *, 4> InvolvedStructType;
};

class StructMemCpyInfo {
public:
  StructType *SourceType;
  StructType *DestintionType;
  unsigned SourceOffset;
  unsigned DestinationOffset;
  unsigned BitsCopied;
  bool HasKnownLength;

  StructMemCpyInfo()
      : SourceType(0), DestintionType(0), SourceOffset(0), DestinationOffset(0),
        BitsCopied(0), HasKnownLength(false) {}

  void setSourceInfo(StructType *SType, unsigned Offset) {
    SourceType = SType;
    SourceOffset = Offset;
  }
  void setDestinationInfo(StructType *DType, unsigned Offset) {
    DestintionType = DType;
    DestinationOffset = Offset;
  }
  void setBitsCopied(unsigned Len) {
    BitsCopied = Len;
    HasKnownLength = true;
  }
};

class FunctionPointerAnalysis {
public:
  // Containers:
  MapVector<StructType *, bool> InvolvedStructs;
  MapVector<llvm::Function *, IndirectCallerPossiblities *> ICP;
  MapVector<StructType *, bool> UnSafeStructs;
  MapVector<StructType *, bool> SafeStructs;
  MapVector<IntrinsicInst *, MemCpyIntrinsicInfo *> MemCpyInfo;
  MapVector<StoreInst *, StoreInstInfo *> StoreInfo;
  MapVector<SelectInst *, SelectInstInfo *> SelectInfo;
  MapVector<PHINode *, PHINodeInfo *> PHIInfo;
  MapVector<CallInst *, CallInstInfo *> CallInfo;
  MapVector<llvm::Function *, bool> MemAllocRoutines;
  MapVector<llvm::Function *, bool> MemFreeRoutines;

  SmallVector<PointerPossibilitiesInfo *, 8> PointerPossibilitiesInfoList;
  SmallVector<CallInst *, 16> IndirectCallList;
  SmallVector<llvm::Function *, 4> AddressTakenExternFunction;
  SmallVector<StructMemCpyInfo *, 4> StructMemCpy;

  const DataLayout *DL;
  TRF TR;

  // Constructor:
  FunctionPointerAnalysis() { resetContainers(); }

  // Destructor:
  ~FunctionPointerAnalysis() {
    // Memory Cleanup IndirectCallerPossiblities
    for (auto &Itr : ICP)
      if (Itr.second)
        delete Itr.second;
    // Memory Cleanup MemCpyIntrinsicInfo
    for (auto &Itr : MemCpyInfo)
      if (Itr.second)
        delete Itr.second;
    // Memory Cleanup StoreInstInfo
    for (auto &Itr : StoreInfo)
      if (Itr.second)
        delete Itr.second;
    // Memory Cleanup SelectInstInfo
    for (auto &Itr : SelectInfo)
      if (Itr.second)
        delete Itr.second;
    // Memory Cleanup PHINodeInfo
    for (auto &Itr : PHIInfo)
      if (Itr.second)
        delete Itr.second;
    // Memory Cleanup CallInstInfo
    for (auto &Itr : CallInfo)
      if (Itr.second)
        delete Itr.second;
    // Memory Cleanup PointerPossibilitiesInfo
    for (PointerPossibilitiesInfo *PPI : PointerPossibilitiesInfoList)
      delete PPI;
    // Memory Cleanup StructMemCpyInfo
    for (StructMemCpyInfo *SMC : StructMemCpy)
      delete SMC;
    // Reset Containers.
    resetContainers();
  }

  // Reset Containers.
  void resetContainers() {
    InvolvedStructs.clear();
    ICP.clear();
    UnSafeStructs.clear();
    SafeStructs.clear();
    MemCpyInfo.clear();
    StoreInfo.clear();
    SelectInfo.clear();
    PHIInfo.clear();
    CallInfo.clear();
    MemAllocRoutines.clear();
    MemFreeRoutines.clear();
    PointerPossibilitiesInfoList.clear();
    IndirectCallList.clear();
    AddressTakenExternFunction.clear();
    StructMemCpy.clear();
    DL = nullptr;
  }

  // Check if its memory allocation call.
  bool isMemAllocCall(CallInst *CI);

  // Check if its memory free call.
  bool isMemFreeCall(CallInst *CI);

  // Check if function is MemAlloc wrapper.
  bool isMemAllocWrapper(llvm::Function *F);

  // Check if function is MemFree wrapper.
  bool isMemFreeWrapper(llvm::Function *F);

  // Initialize memory related routines i.e. malloc, free, etc
  void initMemRelatedRoutines(Module *M);

  // Analyze Module for indirect call possiblity & struct safety
  bool analyzeModule(Module *, TRF);

  // Analyze function for indirect call possiblity & struct safety
  bool analyzeFunction(llvm::Function *);

  // Analyze store instruction
  void analyzeWriteToMemory(Instruction *);

  // Analyze function call
  void analyzeFunctionCall(CallInst *);

  // Analyze cast instruction
  void analyzeCastInst(CastInst *);

  // Identify type escape in function call.
  void identifyTypeEscapeInCall(CallInst *);

  // Mark struct involved in call argument as unsafe.
  void markStructAsUnSafeInCallArgument(CallInst *);

  // Identify address taken extern function in module.
  bool identifyAddressTakenExternFunctions(Module *);

  // Check if User is present in the Global Variable.
  bool CheckUserInGlobalVar(GlobalVariable *LLVMUsed, User *U, llvm::Function *F);

  // Return true if address taken extern functions are safe.
  bool hasAddressTakenSafeExternFunctions(Module *);

  // Check & Identify the involved struct accesses in GEP.
  bool checkStructAccessesInGEP(GetElementPtrInst *,
                                SmallVector<StructType *, 4> &InvolvedTypes);

  // Find the PointerPossibilitiesInfo for a given value.
  bool
  findPointerPossibilitiesInfo(Value *,
                               SmallVector<PointerPossibilitiesInfo *, 4> &);

  // Identify and add the function pointer possiblity from StoreInst.
  void addFuncPointerAssignment(StoreInst *,
                                SmallVector<StructType *, 4> &InvolvedTypes);

  // Check the struct access involved in PointerPossibilitiesInfo is safe.
  bool hasSafePointerPossibilitiesInfo(PointerPossibilitiesInfo *PPI);

  // Process & map the indirect call possiblity with caller possiblity.
  void processIndirectCallPossiblities();

  // Process the indirect calls by resolving it.
  void processPendingIndirectCallForStructSafety();

  // Check collected memcpy operands information for safety.
  void processCollectedMemCpy();

  // Checks source & destination struct are castable or not.
  void checkStructCollections(SmallVector<StructType *, 4> &STCol1,
                              SmallVector<StructType *, 4> &STCol2,
                              llvm::Function *F);

  // For a given value build its usage possiblities for later processing
  bool buildUsagePossiblities(Value *, llvm::Function *,
                              SmallVector<StructType *, 4> &PossibleStruct,
                              SmallVector<GetElementPtrInst *, 4> &PossibleGEP,
                              SmallVector<CallDetails, 4> &PossibleCall,
                              SmallVector<StoreDetails, 4> &PossibleStore,
                              SmallVector<SelectDetails, 4> &PossibleSelect,
                              SmallVector<PHIDetails, 4> &PossiblePHI,
                              MapVector<Value *, bool> &Tracker);

  // Check the ramaining possiblities after buildUsagePossiblities
  bool checkUnHandledPossiblities(Value *I, llvm::Function *F);

  // Check the collected GEPs safety.
  bool isGEPCollectionSafe(SmallVector<GetElementPtrInst *, 4> &PossibleGEP,
                           SmallVector<StructType *, 4> &PossibleStruct);

  // Check the collected CallInst are safe.
  bool isCallCollectionSafe(SmallVector<CallDetails, 4> &PossibleCall,
                            SmallVector<StructType *, 4> &PossibleStruct);

  // Check the collected StoreInst are safe.
  bool isStoreCollectionSafe(SmallVector<StoreDetails, 4> &PossibleStore,
                             SmallVector<StructType *, 4> &PossibleStruct,
                             llvm::Function *F);

  // Check the collected SelectInst are safe.
  bool isSelectCollectionSafe(SmallVector<SelectDetails, 4> &PossibleSelect,
                              SmallVector<StructType *, 4> &PossibleStruct,
                              llvm::Function *F);

  // Check the collected PHINode are safe.
  bool isPHICollectionSafe(SmallVector<PHIDetails, 4> &PossiblePHI,
                           SmallVector<StructType *, 4> &PossibleStruct,
                           llvm::Function *F);

  // Check the possiblity of all struct part of vector start from same address.
  bool isStructCollectionIsCastable(SmallVector<StructType *, 4> &, Module *);

  // Check GEP safety
  bool isGEPSafe(GetElementPtrInst *Gep,
                 SmallVector<StructType *, 4> &PossibleStruct);

  // Try to identify GEP type from offset.
  bool tryDeduceGEPType(GetElementPtrInst *Gep,
                        SmallVector<StructType *, 4> &PossibleStruct,
                        SmallVector<StructType *, 4> &ParentStruct,
                        bool &ScalarType);

  // Given a instruction find parent instruction to it.
  Value *findParentInstruction(Value *V, llvm::Function *F,
                               MapVector<Value *, bool> &Tracker);

  // It calls findParentInstruction & checks other possiblity & safety.
  Value *identifyParentInstruction(Value *V, llvm::Function *F,
                                   MapVector<Value *, bool> &Tracker);

  // Find the last level struct and the field offset for it.
  StructType *findLastLevelStructAndTheAccessOffset(GetElementPtrInst *,
                                                    APInt &, APInt &, bool &,
                                                    bool &);

  GetElementPtrInst *findExpectedGEP(Value *V);

  // Return true if the intrinsic is safe with no-escape
  // and no-alias possiblity
  bool isNoEscapeNoAliasIntrinsic(IntrinsicInst *II);

  // Analyze the indirect call & its arguments.
  void analyzeIndirectCall(CallDetails &CD,
                           SmallVector<StructType *, 4> &PossibleStruct);

  // Traverse & check the usage of input value for safety.
  bool
  traverseDownwardsCheckSafety(Value *V, llvm::Function *F,
                               SmallVector<StructType *, 4> &PossibleStruct);

  // Find the parent of the value then check the safety
  // by calling traverseDownwardsCheckSafety.
  bool
  traverseUpwardsCheckSafety(Value *V, llvm::Function *F,
                             SmallVector<StructType *, 4> &PrePossibleStruct,
                             SmallVector<StructType *, 4> &PossibleStruct);

  // Add indirect call to IndirectCallList.
  void addIndirectCall(CallInst *CI) { IndirectCallList.push_back(CI); }

  // Identify the possible functions for a function pointer.
  void identifyFunctionsForFPTR(Value *, llvm::Function *,
                                SmallVector<Value *, 8> &PossibleFunc,
                                MapVector<Value *, bool> &ValTracker);

  // Identify function possiblity from global constants.
  // if identified return true, else false.
  bool identifyFuncFromGlobalConstArrays(Value *V,
                                         SmallVector<Value *, 8> &PossibleFunc);

  // Given a function find the possible indirect calls to it.
  SmallVector<CallInst *, 4> &findPossibleIndirectCalls(llvm::Function *);

  // Find the PointerPossibilitiesInfo for a given indirect call.
  bool findPointerPossibilitiesInfoForIndirectCall(
      CallInst *, SmallVector<PointerPossibilitiesInfo *, 4> &);

  // Print analysis.
  void dump() {
    // 1. Print UnSafe Structs:
    dbgs() << "UnSafe Structs: \n";
    for (auto &Itr : UnSafeStructs) {
      if (Itr.second) {
        if (Itr.first->hasName())
          dbgs() << "  : " << Itr.first->getName() << "\n";
        else
          dbgs() << "  : "
                 << "__AnonStruct__"
                 << "\n";
      }
    }
    // 2. Print the function pointer possiblity information.
    dbgs() << "\n\nFunction Pointer Possiblity Information: \n";
    for (PointerPossibilitiesInfo *PPI : PointerPossibilitiesInfoList)
      PPI->dump();
  }
};

// Identify underlying type by skipping pointer and array type
Type *GetUnderlyingTypeFromPointerOrArray(Type *Ty);

#endif

