#ifndef LLVM_INTERNAL_H
#define LLVM_INTERNAL_H
#include <vector>
#include <cassert>
#include <map>
#include <string>
#include "llvm/CallingConv.h"
#include "llvm/Intrinsics.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetFolder.h"
#include "llvm/Support/raw_os_ostream.h"
extern "C" {
#include "llvm.h"
}
namespace llvm {
class Module;
class GlobalVariable;
class Function;
class GlobalValue;
class BasicBlock;
class Instruction;
class AllocaInst;
class BranchInst;
class Value;
class Constant;
class ConstantInt;
class Type;
class FunctionType;
class TargetMachine;
class TargetData;
class DebugInfo;
}
using namespace llvm;
typedef IRBuilder<true, TargetFolder> LLVMBuilder;
typedef SmallPtrSet<union tree_node *, 16> treeset;
extern llvm::Module *TheModule;
extern llvm::DebugInfo *TheDebugInfo;
extern llvm::TargetMachine *TheTarget;
extern TargetFolder *TheFolder;
const TargetData &getTargetData();
extern SmallSetVector<Constant *,32> AttributeUsedGlobals;
extern Constant* ConvertMetadataStringToGV(const char* str);
extern void AddAnnotateAttrsToGlobal(GlobalValue *GV, union tree_node* decl);
void changeLLVMConstant(Constant *Old, Constant *New);
void readLLVMTypesStringTable();
void writeLLVMTypesStringTable();
void readLLVMValues();
void writeLLVMValues();
void readLLVMTypeUsers();
void writeLLVMTypeUsers();
void eraseLocalLLVMValues();
void clearTargetBuiltinCache();
const char* extractRegisterName(union tree_node*);
void handleVisibility(union tree_node* decl, GlobalValue *GV);
struct StructTypeConversionInfo;
bool isPaddingElement(union tree_node*, unsigned N);
class TypeConverter {
bool ConvertingStruct;
std::vector<tree_node*> PointersToReresolve;
public:
TypeConverter() : ConvertingStruct(false) {}
const Type *ConvertType(tree_node *type);
static bool GCCTypeOverlapsWithLLVMTypePadding(tree_node *t, const Type *Ty);
const FunctionType *ConvertFunctionType(tree_node *type,
tree_node *decl,
tree_node *static_chain,
CallingConv::ID &CallingConv,
AttrListPtr &PAL);
const FunctionType *ConvertArgListToFnType(tree_node *type,
tree_node *arglist,
tree_node *static_chain,
CallingConv::ID &CallingConv,
AttrListPtr &PAL);
private:
const Type *ConvertRECORD(tree_node *type, tree_node *orig_type);
const Type *ConvertUNION(tree_node *type, tree_node *orig_type);
bool DecodeStructFields(tree_node *Field, StructTypeConversionInfo &Info);
void DecodeStructBitField(tree_node *Field, StructTypeConversionInfo &Info);
void SelectUnionMember(tree_node *type, StructTypeConversionInfo &Info);
};
extern TypeConverter *TheTypeConverter;
inline const Type *ConvertType(tree_node *type) {
return TheTypeConverter->ConvertType(type);
}
uint64_t getINTEGER_CSTVal(tree_node *exp);
bool isInt64(tree_node *t, bool Unsigned);
uint64_t getInt64(tree_node *t, bool Unsigned);
bool isPassedByInvisibleReference(tree_node *type);
bool isSequentialCompatible(tree_node *type);
bool isBitfield(tree_node *field_decl);
tree_node *getDeclaredType(tree_node *field_decl);
bool ValidateRegisterVariable(tree_node *decl);
struct MemRef {
Value *Ptr;
bool Volatile;
private:
unsigned char LogAlign;
public:
MemRef() : Ptr(0), Volatile(false), LogAlign(0) {}
MemRef(Value *P, uint32_t A, bool V) : Ptr(P), Volatile(V) {
assert(isPowerOf2_32(A) && "Alignment not a power of 2!");
LogAlign = Log2_32(A);
}
uint32_t getAlignment() const {
return 1U << LogAlign;
}
};
struct LValue {
Value *Ptr;
unsigned char BitStart;
unsigned char BitSize;
private:
unsigned char LogAlign;
public:
LValue() : Ptr(0), BitStart(255), BitSize(255), LogAlign(0) {}
LValue(Value *P, uint32_t A) : Ptr(P), BitStart(255), BitSize(255) {
assert(isPowerOf2_32(A) && "Alignment not a power of 2!");
LogAlign = Log2_32(A);
}
LValue(Value *P, uint32_t A, unsigned BSt, unsigned BSi)
: Ptr(P), BitStart(BSt), BitSize(BSi) {
assert(BitStart == BSt && BitSize == BSi &&
"Bit values larger than 256?");
assert(isPowerOf2_32(A) && "Alignment not a power of 2!");
LogAlign = Log2_32(A);
}
uint32_t getAlignment() const {
return 1U << LogAlign;
}
bool isBitfield() const { return BitStart != 255; }
};
class TreeToLLVM {
const TargetData &TD;
tree_node *FnDecl;
Function *Fn;
BasicBlock *ReturnBB;
BasicBlock *UnwindBB;
unsigned ReturnOffset;
treeset SeenBlocks;
LLVMBuilder Builder;
Instruction *AllocaInsertionPoint;
std::vector<BitCastInst *> UniquedValues;
IndexedMap<BasicBlock *> LandingPads;
IndexedMap<BasicBlock *> PostPads;
Value *ExceptionValue;
Value *ExceptionSelectorValue;
Function *FuncEHException;
Function *FuncEHSelector;
Function *FuncEHGetTypeID;
public:
TreeToLLVM(tree_node *fndecl);
~TreeToLLVM();
tree_node *getFUNCTION_DECL() const { return FnDecl; }
Function *EmitFunction();
LValue EmitLV(tree_node *exp);
BasicBlock *getIndirectGotoBlock();
void TODO(tree_node *exp = 0);
Value *CastToType(unsigned opcode, Value *V, const Type *Ty);
Value *CastToType(unsigned opcode, Value *V, tree_node *type) {
return CastToType(opcode, V, ConvertType(type));
}
Value *CastToAnyType (Value *V, bool VSigned, const Type* Ty, bool TySigned);
Value *CastToUIntType(Value *V, const Type* Ty);
Value *CastToSIntType(Value *V, const Type* Ty);
Value *CastToFPType(Value *V, const Type* Ty);
Value *BitCastToType(Value *V, const Type *Ty);
AllocaInst *CreateTemporary(const Type *Ty, unsigned align=0);
MemRef CreateTempLoc(const Type *Ty);
void EmitAggregateCopy(MemRef DestLoc, MemRef SrcLoc, tree_node *GCCType);
void push_regions(tree_node *desired, tree_node *grand);
void switchLexicalBlock(tree_node *exp);
void StartFunctionBody();
private:
void setLexicalBlockDepths(tree_node *t, treeset &s, unsigned level);
Function *FinishFunctionBody();
Value *Emit(tree_node *exp, const MemRef *DestLoc);
void EmitBlock(BasicBlock *BB);
void EmitAggregateZero(MemRef DestLoc, tree_node *GCCType);
Value *EmitMemCpy(Value *DestPtr, Value *SrcPtr, Value *Size, unsigned Align);
Value *EmitMemMove(Value *DestPtr, Value *SrcPtr, Value *Size, unsigned Align);
Value *EmitMemSet(Value *DestPtr, Value *SrcVal, Value *Size, unsigned Align);
void EmitLandingPads();
void EmitPostPads();
void EmitUnwindBlock();
bool EmitDebugInfo();
private:
void CreateExceptionValues();
BasicBlock *getPostPad(unsigned RegionNo);
private:
void EmitAutomaticVariableDecl(tree_node *decl);
static bool isNoopCast(Value *V, const Type *Ty);
void HandleMultiplyDefinedGimpleTemporary(tree_node *var);
void EmitAnnotateIntrinsic(Value *V, tree_node *decl);
void EmitTypeGcroot(Value *V, tree_node *decl);
private:
Value *EmitLABEL_EXPR(tree_node *exp);
Value *EmitGOTO_EXPR(tree_node *exp);
Value *EmitRETURN_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitCOND_EXPR(tree_node *exp);
Value *EmitSWITCH_EXPR(tree_node *exp);
Value *EmitLoadOfLValue(tree_node *exp, const MemRef *DestLoc);
Value *EmitOBJ_TYPE_REF(tree_node *exp, const MemRef *DestLoc);
Value *EmitADDR_EXPR(tree_node *exp);
Value *EmitOBJ_TYPE_REF(tree_node *exp);
Value *EmitCALL_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitCallOf(Value *Callee, tree_node *exp, const MemRef *DestLoc,
const AttrListPtr &PAL);
Value *EmitMODIFY_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitNOP_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitCONVERT_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitVIEW_CONVERT_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitNEGATE_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitCONJ_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitABS_EXPR(tree_node *exp);
Value *EmitBIT_NOT_EXPR(tree_node *exp);
Value *EmitTRUTH_NOT_EXPR(tree_node *exp);
Value *EmitEXACT_DIV_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitCompare(tree_node *exp, unsigned UIPred, unsigned SIPred,
unsigned FPPred, const Type *DestTy = 0);
Value *EmitBinOp(tree_node *exp, const MemRef *DestLoc, unsigned Opc);
Value *EmitPtrBinOp(tree_node *exp, unsigned Opc);
Value *EmitTruthOp(tree_node *exp, unsigned Opc);
Value *EmitShiftOp(tree_node *exp, const MemRef *DestLoc, unsigned Opc);
Value *EmitRotateOp(tree_node *exp, unsigned Opc1, unsigned Opc2);
Value *EmitMinMaxExpr(tree_node *exp, unsigned UIPred, unsigned SIPred,
unsigned Opc);
Value *EmitFLOOR_MOD_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitCEIL_DIV_EXPR(tree_node *exp);
Value *EmitFLOOR_DIV_EXPR(tree_node *exp);
Value *EmitROUND_DIV_EXPR(tree_node *exp);
Value *EmitFieldAnnotation(Value *FieldPtr, tree_node *FieldDecl);
Value *EmitEXC_PTR_EXPR(tree_node *exp);
Value *EmitFILTER_EXPR(tree_node *exp);
Value *EmitRESX_EXPR(tree_node *exp);
Value *EmitASM_EXPR(tree_node *exp);
Value *EmitReadOfRegisterVariable(tree_node *vardecl, const MemRef *DestLoc);
void EmitModifyOfRegisterVariable(tree_node *vardecl, Value *RHS);
Value *EmitMoveOfRegVariableToRightReg(Instruction *I, tree_node *decl);
void EmitMemoryBarrier(bool ll, bool ls, bool sl, bool ss, bool device);
Value *BuildVector(const std::vector<Value*> &Elts);
Value *BuildVector(Value *Elt, ...);
Value *BuildVectorShuffle(Value *InVec1, Value *InVec2, ...);
Value *BuildBinaryAtomicBuiltin(tree_node *exp, Intrinsic::ID id);
Value *BuildCmpAndSwapAtomicBuiltin(tree_node *exp, tree_node *type,
bool isBool);
bool EmitBuiltinCall(tree_node *exp, tree_node *fndecl,
const MemRef *DestLoc, Value *&Result);
bool EmitFrontendExpandedBuiltinCall(tree_node *exp, tree_node *fndecl,
const MemRef *DestLoc, Value *&Result);
bool EmitBuiltinUnaryOp(Value *InVal, Value *&Result, Intrinsic::ID Id);
Value *EmitBuiltinSQRT(tree_node *exp);
Value *EmitBuiltinPOWI(tree_node *exp);
Value *EmitBuiltinPOW(tree_node *exp);
bool EmitBuiltinConstantP(tree_node *exp, Value *&Result);
bool EmitBuiltinAlloca(tree_node *exp, Value *&Result);
bool EmitBuiltinExpect(tree_node *exp, const MemRef *DestLoc, Value *&Result);
bool EmitBuiltinExtendPointer(tree_node *exp, Value *&Result);
bool EmitBuiltinVAStart(tree_node *exp);
bool EmitBuiltinVAEnd(tree_node *exp);
bool EmitBuiltinVACopy(tree_node *exp);
bool EmitBuiltinMemCopy(tree_node *exp, Value *&Result,
bool isMemMove, bool SizeCheck);
bool EmitBuiltinMemSet(tree_node *exp, Value *&Result, bool SizeCheck);
bool EmitBuiltinBZero(tree_node *exp, Value *&Result);
bool EmitBuiltinPrefetch(tree_node *exp);
bool EmitBuiltinReturnAddr(tree_node *exp, Value *&Result, bool isFrame);
bool EmitBuiltinExtractReturnAddr(tree_node *exp, Value *&Result);
bool EmitBuiltinFrobReturnAddr(tree_node *exp, Value *&Result);
bool EmitBuiltinStackSave(tree_node *exp, Value *&Result);
bool EmitBuiltinStackRestore(tree_node *exp);
bool EmitBuiltinDwarfCFA(tree_node *exp, Value *&Result);
bool EmitBuiltinDwarfSPColumn(tree_node *exp, Value *&Result);
bool EmitBuiltinEHReturnDataRegno(tree_node *exp, Value *&Result);
bool EmitBuiltinEHReturn(tree_node *exp, Value *&Result);
bool EmitBuiltinInitDwarfRegSizes(tree_node *exp, Value *&Result);
bool EmitBuiltinUnwindInit(tree_node *exp, Value *&Result);
bool EmitBuiltinInitTrampoline(tree_node *exp, Value *&Result);
void EmitLoadFromComplex(Value *&Real, Value *&Imag, MemRef SrcComplex);
void EmitStoreToComplex(MemRef DestComplex, Value *Real, Value *Imag);
void EmitCOMPLEX_CST(tree_node *exp, const MemRef *DestLoc);
void EmitCOMPLEX_EXPR(tree_node *exp, const MemRef *DestLoc);
Value *EmitComplexBinOp(tree_node *exp, const MemRef *DestLoc);
LValue EmitLV_ARRAY_REF(tree_node *exp);
LValue EmitLV_BIT_FIELD_REF(tree_node *exp);
LValue EmitLV_COMPONENT_REF(tree_node *exp);
LValue EmitLV_DECL(tree_node *exp);
LValue EmitLV_EXC_PTR_EXPR(tree_node *exp);
LValue EmitLV_FILTER_EXPR(tree_node *exp);
LValue EmitLV_INDIRECT_REF(tree_node *exp);
LValue EmitLV_VIEW_CONVERT_EXPR(tree_node *exp);
LValue EmitLV_WITH_SIZE_EXPR(tree_node *exp);
LValue EmitLV_XXXXPART_EXPR(tree_node *exp, unsigned Idx);
Value *EmitINTEGER_CST(tree_node *exp);
Value *EmitREAL_CST(tree_node *exp);
Value *EmitCONSTRUCTOR(tree_node *exp, const MemRef *DestLoc);
bool TargetIntrinsicLower(tree_node *exp,
unsigned FnCode,
const MemRef *DestLoc,
Value *&Result,
const Type *ResultType,
std::vector<Value*> &Ops);
public:
Constant *EmitLV_LABEL_DECL(tree_node *exp);
};
extern TreeToLLVM *TheTreeToLLVM;
class TreeConstantToLLVM {
public:
static Constant *Convert(tree_node *exp);
static Constant *ConvertINTEGER_CST(tree_node *exp);
static Constant *ConvertREAL_CST(tree_node *exp);
static Constant *ConvertVECTOR_CST(tree_node *exp);
static Constant *ConvertSTRING_CST(tree_node *exp);
static Constant *ConvertCOMPLEX_CST(tree_node *exp);
static Constant *ConvertNOP_EXPR(tree_node *exp);
static Constant *ConvertCONVERT_EXPR(tree_node *exp);
static Constant *ConvertBinOp_CST(tree_node *exp);
static Constant *ConvertCONSTRUCTOR(tree_node *exp);
static Constant *ConvertArrayCONSTRUCTOR(tree_node *exp);
static Constant *ConvertRecordCONSTRUCTOR(tree_node *exp);
static Constant *ConvertUnionCONSTRUCTOR(tree_node *exp);
static Constant *EmitLV(tree_node *exp);
static Constant *EmitLV_Decl(tree_node *exp);
static Constant *EmitLV_LABEL_DECL(tree_node *exp);
static Constant *EmitLV_COMPLEX_CST(tree_node *exp);
static Constant *EmitLV_STRING_CST(tree_node *exp);
static Constant *EmitLV_COMPONENT_REF(tree_node *exp);
static Constant *EmitLV_ARRAY_REF(tree_node *exp);
};
#endif