blob: fdafbf008b617ca1dd79aab0c57ffe2c64dc3aab [file] [log] [blame]
//=---- Internals.h - Interface between the backend components ----*- C++ -*-=//
//
// Copyright (C) 2005 to 2013 Chris Lattner, Duncan Sands et al.
//
// This file is part of DragonEgg.
//
// DragonEgg is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2, or (at your option) any later version.
//
// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// DragonEgg; see the file COPYING. If not, write to the Free Software
// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
//
//===----------------------------------------------------------------------===//
// This file declares the internal interfaces shared among the dragonegg files.
//===----------------------------------------------------------------------===//
#ifndef DRAGONEGG_INTERNALS_H
#define DRAGONEGG_INTERNALS_H
// LLVM headers
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/TargetFolder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
struct basic_block_def;
union gimple_statement_d;
union tree_node;
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 TargetMachine;
class DataLayout;
template <typename> class AssertingVH;
template <typename> class TrackingVH;
}
class DebugInfo;
typedef llvm::IRBuilder<true, llvm::TargetFolder> LLVMBuilder;
// Global state.
/// TheModule - This is the current global module that we are compiling into.
///
extern llvm::Module *TheModule;
/// TheDebugInfo - This object is responsible for gather all debug information.
/// If it's value is NULL then no debug information should be gathered.
extern DebugInfo *TheDebugInfo;
/// TheTarget - The current target being compiled for.
///
extern llvm::TargetMachine *TheTarget;
/// TheFolder - The constant folder to use.
extern llvm::TargetFolder *TheFolder;
/// getDataLayout - Return the current DataLayout object from TheTarget.
const llvm::DataLayout &getDataLayout();
/// flag_default_initialize_globals - Whether global variables with no explicit
/// initial value should be zero initialized.
extern bool flag_default_initialize_globals;
/// flag_odr - Whether the language being compiled obeys the One Definition Rule
/// (i.e. if the same function is defined in multiple compilation units, all the
/// definitions are equivalent).
extern bool flag_odr;
/// flag_functions_from_args - Construct function prototypes from the argument
/// list, ignoring the function type. This is helpful if the language front-end
/// sometimes creates functions and/or calls where the arguments do not match
/// the arguments given in the function type.
extern bool flag_functions_from_args;
/// AttributeUsedGlobals - The list of globals that are marked attribute(used).
extern llvm::SmallSetVector<llvm::Constant *, 32> AttributeUsedGlobals;
extern llvm::Constant *ConvertMetadataStringToGV(const char *str);
/// AddAnnotateAttrsToGlobal - Adds decls that have a
/// annotate attribute to a vector to be emitted later.
extern void AddAnnotateAttrsToGlobal(llvm::GlobalValue *GV, tree_node *decl);
// Mapping between GCC declarations and LLVM values. The GCC declaration must
// satisfy HAS_RTL_P.
/// DECL_LLVM - Returns the LLVM declaration of a global variable or function.
extern llvm::Value *make_decl_llvm(tree_node *);
#define DECL_LLVM(NODE) make_decl_llvm(NODE)
/// SET_DECL_LLVM - Set the DECL_LLVM for NODE to LLVM.
extern llvm::Value *set_decl_llvm(tree_node *, llvm::Value *);
#define SET_DECL_LLVM(NODE, LLVM) set_decl_llvm(NODE, LLVM)
/// DECL_LLVM_IF_SET - The DECL_LLVM for NODE, if it is set, or NULL, if it is
/// not set.
extern llvm::Value *get_decl_llvm(tree_node *);
#define DECL_LLVM_IF_SET(NODE) (HAS_RTL_P(NODE) ? get_decl_llvm(NODE) : NULL)
/// DECL_LLVM_SET_P - Returns nonzero if the DECL_LLVM for NODE has already
/// been set.
#define DECL_LLVM_SET_P(NODE) (DECL_LLVM_IF_SET(NODE) != NULL)
/// DEFINITION_LLVM - Ensures that the body or initial value of the given GCC
/// global will be output, and returns a declaration for it.
llvm::Value *make_definition_llvm(tree_node *decl);
#define DEFINITION_LLVM(NODE) make_definition_llvm(NODE)
// Mapping between GCC declarations and non-negative integers. The GCC
// declaration must not satisfy HAS_RTL_P.
void changeLLVMConstant(llvm::Constant *Old, llvm::Constant *New);
void register_ctor_dtor(llvm::Function *, int, bool);
const char *extractRegisterName(tree_node *);
void handleVisibility(tree_node *decl, llvm::GlobalValue *GV);
/// Return true if and only if field no. N from struct type T is a padding
/// element added to match llvm struct type size and gcc struct type size.
bool isPaddingElement(tree_node *, unsigned N);
/// getDefaultValue - Return the default value to use for a constant or global
/// that has no value specified. For example in C like languages such variables
/// are initialized to zero, while in Ada they hold an undefined value.
inline llvm::Constant *getDefaultValue(llvm::Type *Ty) {
return flag_default_initialize_globals ? llvm::Constant::getNullValue(Ty)
: llvm::UndefValue::get(Ty);
}
/// isPassedByInvisibleReference - Return true if the specified type should be
/// passed by 'invisible reference'. In other words, instead of passing the
/// thing by value, pass the address of a temporary.
bool isPassedByInvisibleReference(tree_node *type);
/// ValidateRegisterVariable - Check that a static "asm" variable is
/// well-formed. If not, emit error messages and return true. If so, return
/// false.
bool ValidateRegisterVariable(tree_node *decl);
/// MemRef - This struct holds the information needed for a memory access:
/// a pointer to the memory, its alignment and whether the access is volatile.
class MemRef {
public:
llvm::Value *Ptr;
bool Volatile;
private:
unsigned char LogAlign;
public:
explicit MemRef() : Ptr(0), Volatile(false), LogAlign(0) {}
explicit MemRef(llvm::Value *P, uint32_t A, bool V) : Ptr(P), Volatile(V) {
setAlignment(A);
}
uint32_t getAlignment() const { return 1U << LogAlign; }
void setAlignment(uint32_t A) {
// Forbid alignment 0 along with non-power-of-2 alignment values.
assert(llvm::isPowerOf2_32(A) && "Alignment not a power of 2!");
LogAlign = (unsigned char) llvm::Log2_32(A);
}
};
/// LValue - This struct represents an lvalue in the program. In particular,
/// the Ptr member indicates the memory that the lvalue lives in. Alignment
/// is the alignment of the memory (in bytes).If this is a bitfield reference,
/// BitStart indicates the first bit in the memory that is part of the field
/// and BitSize indicates the extent.
///
/// "LValue" is intended to be a light-weight object passed around by-value.
class LValue : public MemRef {
public:
unsigned char BitStart;
unsigned char BitSize;
public:
explicit LValue() : BitStart(255), BitSize(255) {}
explicit LValue(MemRef &M) : MemRef(M), BitStart(255), BitSize(255) {}
LValue(llvm::Value *P, uint32_t A, bool V = false)
: MemRef(P, A, V), BitStart(255), BitSize(255) {}
LValue(llvm::Value *P, uint32_t A, unsigned BSt, unsigned BSi, bool V = false)
: MemRef(P, A, V), BitStart((unsigned char) BSt),
BitSize((unsigned char) BSi) {
assert(BitStart == BSt && BitSize == BSi && "Bit values larger than 256?");
}
bool isBitfield() const { return BitStart != 255; }
};
/// PhiRecord - This struct holds the LLVM PHI node associated with a GCC phi.
struct PhiRecord {
gimple_statement_d *gcc_phi;
llvm::PHINode *PHI;
};
/// TreeToLLVM - An instance of this class is created and used to convert the
/// body of each function to LLVM.
///
class TreeToLLVM {
// State that is initialized when the function starts.
const llvm::DataLayout &DL;
tree_node *FnDecl;
llvm::Function *Fn;
llvm::BasicBlock *ReturnBB;
unsigned ReturnOffset;
// State that changes as the function is emitted.
/// Builder - Instruction creator, the location to insert into is always the
/// same as &Fn->back().
LLVMBuilder Builder;
// AllocaInsertionPoint - Place to insert alloca instructions. Lazily created
// and managed by CreateTemporary.
llvm::Instruction *AllocaInsertionPoint;
// SSAInsertionPoint - Place to insert reads corresponding to SSA default
// definitions.
llvm::Instruction *SSAInsertionPoint;
/// BasicBlocks - Map from GCC to LLVM basic blocks.
llvm::DenseMap<basic_block_def *, llvm::BasicBlock *> BasicBlocks;
/// LocalDecls - Map from local declarations to their associated LLVM values.
llvm::DenseMap<tree_node *, llvm::AssertingVH<llvm::Value> > LocalDecls;
/// PendingPhis - Phi nodes which have not yet been populated with operands.
llvm::SmallVector<PhiRecord, 16> PendingPhis;
// SSANames - Map from GCC ssa names to the defining LLVM value.
llvm::DenseMap<tree_node *, llvm::TrackingVH<llvm::Value> > SSANames;
public:
//===---------------------- Local Declarations --------------------------===//
/// DECL_LOCAL - Like DECL_LLVM, returns the LLVM declaration of a variable or
/// function. However DECL_LOCAL can be used with declarations local to the
/// current function as well as with global declarations.
llvm::Value *make_decl_local(tree_node *);
#define DECL_LOCAL(NODE) make_decl_local(NODE)
/// DEFINITION_LOCAL - Like DEFINITION_LLVM, ensures that the initial value or
/// body of a variable or function will be output. However DEFINITION_LOCAL
/// can be used with declarations local to the current function as well as
/// with global declarations.
llvm::Value *make_definition_local(tree_node *);
#define DEFINITION_LOCAL(NODE) make_definition_local(NODE)
/// SET_DECL_LOCAL - Set the DECL_LOCAL for NODE to LLVM.
llvm::Value *set_decl_local(tree_node *, llvm::Value *);
#define SET_DECL_LOCAL(NODE, LLVM) set_decl_local(NODE, LLVM)
/// DECL_LOCAL_IF_SET - The DECL_LOCAL for NODE, if it is set, or NULL, if it
/// is not set.
llvm::Value *get_decl_local(tree_node *);
#define DECL_LOCAL_IF_SET(NODE) (HAS_RTL_P(NODE) ? get_decl_local(NODE) : NULL)
/// DECL_LOCAL_SET_P - Returns nonzero if the DECL_LOCAL for NODE has already
/// been set.
#define DECL_LOCAL_SET_P(NODE) (DECL_LOCAL_IF_SET(NODE) != NULL)
private:
//===---------------------- Exception Handling --------------------------===//
/// NormalInvokes - Mapping from landing pad number to the set of invoke
/// instructions that unwind to that landing pad.
llvm::SmallVector<llvm::SmallVector<llvm::InvokeInst *, 8>, 16> NormalInvokes;
/// ExceptionPtrs - Mapping from EH region index to the local holding the
/// exception pointer for that region.
llvm::SmallVector<llvm::AllocaInst *, 16> ExceptionPtrs;
/// ExceptionFilters - Mapping from EH region index to the local holding the
/// filter value for that region.
llvm::SmallVector<llvm::AllocaInst *, 16> ExceptionFilters;
/// FailureBlocks - Mapping from the index of a must-not-throw EH region to
/// the block containing the failure code for the region (the code that is
/// run if an exception is thrown in this region).
llvm::SmallVector<llvm::BasicBlock *, 16> FailureBlocks;
public:
TreeToLLVM(tree_node *fndecl);
~TreeToLLVM();
/// getFUNCTION_DECL - Return the FUNCTION_DECL node for the current function
/// being compiled.
tree_node *getFUNCTION_DECL() const { return FnDecl; }
/// EmitFunction - Convert 'fndecl' to LLVM code.
llvm::Function *EmitFunction();
/// EmitBasicBlock - Convert the given basic block.
void EmitBasicBlock(basic_block_def *bb);
/// EmitLV - Convert the specified l-value tree node to LLVM code, returning
/// the address of the result.
LValue EmitLV(tree_node *exp);
/// CastToAnyType - Cast the specified value to the specified type regardless
/// of the types involved. This is an inferred cast.
llvm::Value *CastToAnyType(llvm::Value *Src, bool SrcIsSigned,
llvm::Type *DstTy, bool DstIsSigned);
llvm::Constant *CastToAnyType(llvm::Constant *Src, bool SrcIsSigned,
llvm::Type *DstTy, bool DstIsSigned);
/// CastFromSameSizeInteger - Cast an integer (or vector of integer) value to
/// the given scalar (resp. vector of scalar) type of the same bitwidth.
llvm::Value *CastFromSameSizeInteger(llvm::Value *V, llvm::Type *Ty);
/// CastToSameSizeInteger - Cast the specified scalar (or vector of scalar)
/// value to an integer (resp. vector of integer) of the same bit width.
llvm::Value *CastToSameSizeInteger(llvm::Value *V);
/// CastToFPType - Cast the specified value to the specified type assuming
/// that V's type and Ty are floating point types. This arbitrates between
/// BitCast, FPTrunc and FPExt.
llvm::Value *CastToFPType(llvm::Value *V, llvm::Type *Ty);
/// CreateAnyAdd - Add two LLVM scalar values with the given GCC type. Does
/// not support complex numbers. The type is used to set overflow flags.
llvm::Value *CreateAnyAdd(llvm::Value *LHS, llvm::Value *RHS,
tree_node *type);
/// CreateAnyMul - Multiply two LLVM scalar values with the given GCC type.
/// Does not support complex numbers. The type is used to set overflow flags.
llvm::Value *CreateAnyMul(llvm::Value *LHS, llvm::Value *RHS,
tree_node *type);
/// CreateAnyNeg - Negate an LLVM scalar value with the given GCC type. Does
/// not support complex numbers. The type is used to set overflow flags.
llvm::Value *CreateAnyNeg(llvm::Value *V, tree_node *type);
/// CreateAnySub - Subtract two LLVM scalar values with the given GCC type.
/// Does not support complex numbers.
llvm::Value *CreateAnySub(llvm::Value *LHS, llvm::Value *RHS,
tree_node *type);
/// CreateTemporary - Create a new alloca instruction of the specified type,
/// inserting it into the entry block and returning it. The resulting
/// instruction's type is a pointer to the specified type.
llvm::AllocaInst *CreateTemporary(llvm::Type *Ty, unsigned align = 0);
/// CreateTempLoc - Like CreateTemporary, but returns a MemRef.
MemRef CreateTempLoc(llvm::Type *Ty);
/// EmitAggregateCopy - Copy the elements from SrcLoc to DestLoc, using the
/// GCC type specified by GCCType to know which elements to copy.
void EmitAggregateCopy(MemRef DestLoc, MemRef SrcLoc, tree_node *GCCType);
/// EmitAggregate - Store the specified tree node into the location given by
/// DestLoc.
void EmitAggregate(tree_node *exp, const MemRef &DestLoc);
private : // Helper functions.
/// StartFunctionBody - Start the emission of 'fndecl', outputing all
/// declarations for parameters and setting things up.
void StartFunctionBody();
/// FinishFunctionBody - Once the body of the function has been emitted, this
/// cleans up and returns the result function.
llvm::Function *FinishFunctionBody();
/// EmitVariablesInScope - Output a declaration for every variable in the
/// given scope.
void EmitVariablesInScope(tree_node *scope);
/// PopulatePhiNodes - Populate generated phi nodes with their operands.
void PopulatePhiNodes();
/// getBasicBlock - Find or create the LLVM basic block corresponding to BB.
llvm::BasicBlock *getBasicBlock(basic_block_def *bb);
/// getLabelDeclBlock - Lazily get and create a basic block for the specified
/// label.
llvm::BasicBlock *getLabelDeclBlock(tree_node *LabelDecl);
/// DefineSSAName - Use the given value as the definition of the given SSA
/// name. Returns the provided value as a convenience.
llvm::Value *DefineSSAName(tree_node *reg, llvm::Value *Val);
/// BeginBlock - Add the specified basic block to the end of the function. If
/// the previous block falls through into it, add an explicit branch.
void BeginBlock(llvm::BasicBlock *BB);
/// CopyElementByElement - Recursively traverse the potentially aggregate
/// src/dest ptrs, copying all of the elements. Helper for EmitAggregateCopy.
void CopyElementByElement(MemRef DestLoc, MemRef SrcLoc, tree_node *type);
/// ZeroElementByElement - Recursively traverse the potentially aggregate
/// DestLoc, zero'ing all of the elements. Helper for EmitAggregateZero.
void ZeroElementByElement(MemRef DestLoc, tree_node *type);
/// EmitAggregateZero - Zero the elements of DestLoc.
void EmitAggregateZero(MemRef DestLoc, tree_node *type);
/// EmitMemCpy/EmitMemMove/EmitMemSet - Emit an llvm.memcpy/llvm.memmove or
/// llvm.memset call with the specified operands. Returns DestPtr bitcast
/// to i8*.
llvm::Value *EmitMemCpy(llvm::Value *DestPtr, llvm::Value *SrcPtr,
llvm::Value *Size, unsigned Align);
llvm::Value *EmitMemMove(llvm::Value *DestPtr, llvm::Value *SrcPtr,
llvm::Value *Size, unsigned Align);
llvm::Value *EmitMemSet(llvm::Value *DestPtr, llvm::Value *SrcVal,
llvm::Value *Size, unsigned Align);
/// EmitLandingPads - Emit EH landing pads.
void EmitLandingPads();
/// EmitFailureBlocks - Emit the blocks containing failure code executed when
/// an exception is thrown in a must-not-throw region.
void EmitFailureBlocks();
/// EmitDebugInfo - Return true if debug info is to be emitted for current
/// function.
bool EmitDebugInfo();
private : // Helpers for exception handling.
/// getExceptionPtr - Return the local holding the exception pointer for the
/// given exception handling region, creating it if necessary.
llvm::AllocaInst *getExceptionPtr(int RegionNo);
/// getExceptionFilter - Return the local holding the filter value for the
/// given exception handling region, creating it if necessary.
llvm::AllocaInst *getExceptionFilter(int RegionNo);
/// getFailureBlock - Return the basic block containing the failure code for
/// the given exception handling region, creating it if necessary.
llvm::BasicBlock *getFailureBlock(int RegionNo);
private:
void EmitAutomaticVariableDecl(tree_node *decl);
/// EmitAnnotateIntrinsic - Emits call to annotate attr intrinsic
void EmitAnnotateIntrinsic(llvm::Value *V, tree_node *decl);
/// EmitTypeGcroot - Emits call to make type a gcroot
void EmitTypeGcroot(llvm::Value *V);
private:
//===------------------ Render* - Convert GIMPLE to LLVM ----------------===//
void RenderGIMPLE_ASM(gimple_statement_d *stmt);
void RenderGIMPLE_ASSIGN(gimple_statement_d *stmt);
void RenderGIMPLE_CALL(gimple_statement_d *stmt);
void RenderGIMPLE_COND(gimple_statement_d *stmt);
void RenderGIMPLE_EH_DISPATCH(gimple_statement_d *stmt);
void RenderGIMPLE_GOTO(gimple_statement_d *stmt);
void RenderGIMPLE_RESX(gimple_statement_d *stmt);
void RenderGIMPLE_RETURN(gimple_statement_d *stmt);
void RenderGIMPLE_SWITCH(gimple_statement_d *stmt);
// Render helpers.
/// EmitAssignRHS - Convert the RHS of a scalar GIMPLE_ASSIGN to LLVM.
llvm::Value *EmitAssignRHS(gimple_statement_d *stmt);
/// EmitAssignSingleRHS - Helper for EmitAssignRHS. Handles those RHS that
/// are not register expressions.
llvm::Value *EmitAssignSingleRHS(tree_node *rhs);
/// OutputCallRHS - Convert the RHS of a GIMPLE_CALL.
llvm::Value *OutputCallRHS(gimple_statement_d *stmt, const MemRef *DestLoc);
/// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS.
void WriteScalarToLHS(tree_node *lhs, llvm::Value *Scalar);
private:
//===---------- EmitReg* - Convert register expression to LLVM ----------===//
/// TriviallyTypeConvert - Convert the given value to the given type, assuming
/// that the original and target types are LLVM register types that correspond
/// to GCC scalar types t1 and t2 satisfying useless_type_conversion_p(t1, t2)
/// or useless_type_conversion_p(t2, t1).
llvm::Value *TriviallyTypeConvert(llvm::Value *V, llvm::Type *Ty) {
// If useless_type_conversion_p(t1, t2) holds then the corresponding LLVM
// register types are either equal or are both pointer types.
if (V->getType() == Ty)
return V;
assert(V->getType()->isPointerTy() && Ty->isPointerTy() && "Not trivial!");
return Builder.CreateBitCast(V, Ty);
}
/// EmitRegister - Convert the specified gimple register or local constant of
/// register type to an LLVM value. Only creates code in the entry block.
llvm::Value *EmitRegister(tree_node *reg);
/// EmitRegisterWithCast - Utility method that calls EmitRegister, then casts
/// the returned value to the given register type.
llvm::Value *EmitRegisterWithCast(tree_node *reg, tree_node *type);
/// EmitReg_SSA_NAME - Return the defining value of the given SSA_NAME.
/// Only creates code in the entry block.
llvm::Value *EmitReg_SSA_NAME(tree_node *reg);
// Unary expressions.
llvm::Value *EmitReg_ABS_EXPR(tree_node *op);
llvm::Value *EmitReg_BIT_NOT_EXPR(tree_node *op);
llvm::Value *EmitReg_CONJ_EXPR(tree_node *op);
llvm::Value *EmitReg_CONVERT_EXPR(tree_node *type, tree_node *op);
llvm::Value *EmitReg_NEGATE_EXPR(tree_node *op);
llvm::Value *EmitReg_PAREN_EXPR(tree_node *exp);
llvm::Value *EmitReg_TRUTH_NOT_EXPR(tree_node *type, tree_node *op);
// Comparisons.
/// EmitCompare - Compare LHS with RHS using the appropriate comparison code.
/// The result is an i1 boolean.
llvm::Value *EmitCompare(tree_node *lhs, tree_node *rhs, unsigned code);
// Binary expressions.
llvm::Value *EmitReg_MinMaxExpr(tree_node *op0, tree_node *op1,
unsigned UIPred, unsigned SIPred,
unsigned Opc);
llvm::Value *EmitReg_ReducMinMaxExpr(tree_node *op, unsigned UIPred,
unsigned SIPred, unsigned Opc);
llvm::Value *EmitReg_RotateOp(tree_node *type, tree_node *op0, tree_node *op1,
unsigned Opc1, unsigned Opc2);
llvm::Value *EmitReg_ShiftOp(tree_node *op0, tree_node *op1, unsigned Opc);
llvm::Value *EmitReg_VecShiftOp(tree_node *op0, tree_node *op1,
bool isLeftShift);
llvm::Value *EmitReg_TruthOp(tree_node *type, tree_node *op0, tree_node *op1,
unsigned Opc);
llvm::Value *EmitReg_VecUnpackHiExpr(tree_node *type, tree_node *op0);
llvm::Value *EmitReg_VecUnpackLoExpr(tree_node *type, tree_node *op0);
llvm::Value *EmitReg_BIT_AND_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_BIT_IOR_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_BIT_XOR_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_CEIL_DIV_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_COMPLEX_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_FLOOR_DIV_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_FLOOR_MOD_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_MINUS_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_MULT_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_PLUS_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_POINTER_PLUS_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_RDIV_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_REDUC_PLUS_EXPR(tree_node *op);
llvm::Value *EmitReg_ROUND_DIV_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_TRUNC_DIV_EXPR(tree_node *op0, tree_node *op1,
bool isExact);
llvm::Value *EmitReg_TRUNC_MOD_EXPR(tree_node *op0, tree_node *op1);
#if (GCC_MINOR < 7)
llvm::Value *EmitReg_VEC_EXTRACT_EVEN_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_VEC_EXTRACT_ODD_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_VEC_INTERLEAVE_HIGH_EXPR(tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_VEC_INTERLEAVE_LOW_EXPR(tree_node *op0, tree_node *op1);
#endif
llvm::Value *EmitReg_VEC_PACK_FIX_TRUNC_EXPR(tree_node *type, tree_node *op0,
tree_node *op1);
llvm::Value *
EmitReg_VEC_PACK_TRUNC_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
llvm::Value *EmitReg_VEC_WIDEN_MULT_HI_EXPR(tree_node *type, tree_node *op0,
tree_node *op1);
llvm::Value *EmitReg_VEC_WIDEN_MULT_LO_EXPR(tree_node *type, tree_node *op0,
tree_node *op1);
llvm::Value *
EmitReg_WIDEN_MULT_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
// Ternary expressions.
llvm::Value *EmitReg_CondExpr(tree_node *op0, tree_node *op1, tree_node *op2);
#if (GCC_MINOR > 5)
llvm::Value *EmitReg_FMA_EXPR(tree_node *op0, tree_node *op1, tree_node *op2);
#endif
#if (GCC_MINOR > 6)
llvm::Value *EmitReg_VEC_PERM_EXPR(tree_node *op0, tree_node *op1,
tree_node *op2);
#endif
llvm::Value *EmitLoadOfLValue(tree_node *exp);
llvm::Value *EmitOBJ_TYPE_REF(tree_node *exp);
llvm::Value *EmitADDR_EXPR(tree_node *exp);
#if (GCC_MINOR < 7)
llvm::Value *EmitCondExpr(tree_node *exp);
#endif
llvm::Value *EmitCallOf(llvm::Value *Callee, gimple_statement_d *stmt,
const MemRef *DestLoc, const llvm::AttributeSet &PAL);
llvm::CallInst *EmitSimpleCall(llvm::StringRef CalleeName,
tree_node *ret_type,
/* arguments */ ...) LLVM_END_WITH_NULL;
llvm::Value *EmitFieldAnnotation(llvm::Value *FieldPtr, tree_node *FieldDecl);
// Inline Assembly and Register Variables.
llvm::Value *EmitReadOfRegisterVariable(tree_node *vardecl);
void EmitModifyOfRegisterVariable(tree_node *vardecl, llvm::Value *RHS);
// Helpers for Builtin Function Expansion.
llvm::Value *BuildVector(const std::vector<llvm::Value *> &Elts);
llvm::Value *BuildVector(llvm::Value *Elt, ...);
llvm::Value *BuildVectorShuffle(llvm::Value *InVec1, llvm::Value *InVec2, ...);
llvm::Value *BuildBinaryAtomic(gimple_statement_d *stmt,
llvm::AtomicRMWInst::BinOp Kind,
unsigned PostOp = 0);
llvm::Value *
BuildCmpAndSwapAtomic(gimple_statement_d *stmt, unsigned Bits, bool isBool);
// Builtin Function Expansion.
bool EmitBuiltinCall(gimple_statement_d *stmt, tree_node *fndecl,
const MemRef *DestLoc, llvm::Value *&Result);
bool EmitFrontendExpandedBuiltinCall(gimple_statement_d *stmt,
tree_node *fndecl, const MemRef *DestLoc,
llvm::Value *&Result);
bool EmitBuiltinUnaryOp(llvm::Value *InVal, llvm::Value *&Result,
llvm::Intrinsic::ID Id);
llvm::Value *
EmitBuiltinBitCountIntrinsic(gimple_statement_d *stmt,
llvm::Intrinsic::ID Id);
llvm::Value *EmitBuiltinSQRT(gimple_statement_d *stmt);
llvm::Value *EmitBuiltinPOWI(gimple_statement_d *stmt);
llvm::Value *EmitBuiltinPOW(gimple_statement_d *stmt);
llvm::Value *EmitBuiltinLCEIL(gimple_statement_d *stmt);
llvm::Value *EmitBuiltinLFLOOR(gimple_statement_d *stmt);
llvm::Value *EmitBuiltinLROUND(gimple_statement_d *stmt);
llvm::Value *EmitBuiltinCEXPI(gimple_statement_d *stmt);
llvm::Value *EmitBuiltinSIGNBIT(gimple_statement_d *stmt);
bool EmitBuiltinAdjustTrampoline(gimple_statement_d *stmt,
llvm::Value *&Result);
bool EmitBuiltinAlloca(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinAllocaWithAlign(gimple_statement_d *stmt,
llvm::Value *&Result);
#if (GCC_MINOR > 6)
bool EmitBuiltinAssumeAligned(gimple_statement_d *stmt, llvm::Value *&Result);
#endif
bool EmitBuiltinBZero(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinConstantP(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinExpect(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinExtendPointer(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinExtractReturnAddr(gimple_statement_d *stmt,
llvm::Value *&Result);
bool EmitBuiltinFrobReturnAddr(gimple_statement_d *stmt,
llvm::Value *&Result);
bool EmitBuiltinInitTrampoline(gimple_statement_d *stmt, bool OnStack);
bool EmitBuiltinMemCopy(gimple_statement_d *stmt, llvm::Value *&Result,
bool isMemMove, bool SizeCheck);
bool EmitBuiltinMemSet(gimple_statement_d *stmt, llvm::Value *&Result,
bool SizeCheck);
bool EmitBuiltinPrefetch(gimple_statement_d *stmt);
bool EmitBuiltinReturnAddr(gimple_statement_d *stmt, llvm::Value *&Result,
bool isFrame);
bool EmitBuiltinStackRestore(gimple_statement_d *stmt);
bool EmitBuiltinStackSave(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinUnreachable();
bool EmitBuiltinVACopy(gimple_statement_d *stmt);
bool EmitBuiltinVAEnd(gimple_statement_d *stmt);
bool EmitBuiltinVAStart(gimple_statement_d *stmt);
bool EmitBuiltinEHCopyValues(gimple_statement_d *stmt);
bool EmitBuiltinEHFilter(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinEHPointer(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinDwarfCFA(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinDwarfSPColumn(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinEHReturnDataRegno(gimple_statement_d *stmt,
llvm::Value *&Result);
bool EmitBuiltinEHReturn(gimple_statement_d *stmt, llvm::Value *&Result);
bool EmitBuiltinInitDwarfRegSizes(gimple_statement_d *stmt,
llvm::Value *&Result);
bool EmitBuiltinUnwindInit(gimple_statement_d *stmt, llvm::Value *&Result);
// Complex Math Expressions.
llvm::Value *CreateComplex(llvm::Value *Real, llvm::Value *Imag);
void SplitComplex(llvm::Value *Complex, llvm::Value *&Real,
llvm::Value *&Imag);
// L-Value Expressions.
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_INDIRECT_REF(tree_node *exp);
#if (GCC_MINOR > 5)
LValue EmitLV_MEM_REF(tree_node *exp);
#endif
#if (GCC_MINOR < 6)
LValue EmitLV_MISALIGNED_INDIRECT_REF(tree_node *exp);
#endif
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);
LValue EmitLV_SSA_NAME(tree_node *exp);
LValue EmitLV_TARGET_MEM_REF(tree_node *exp);
// Constant Expressions.
llvm::Value *EmitINTEGER_CST(tree_node *exp);
llvm::Value *EmitREAL_CST(tree_node *exp);
llvm::Value *EmitCONSTRUCTOR(tree_node *exp, const MemRef *DestLoc);
// Emit helpers.
/// EmitMinInvariant - The given value is constant in this function. Return
/// the corresponding LLVM value. Only creates code in the entry block.
llvm::Value *EmitMinInvariant(tree_node *reg);
/// EmitInvariantAddress - The given address is constant in this function.
/// Return the corresponding LLVM value. Only creates code in the entry block.
llvm::Value *EmitInvariantAddress(tree_node *addr);
/// EmitRegisterConstant - Convert the given global constant of register type
/// to an LLVM constant. Creates no code, only constants.
llvm::Constant *EmitRegisterConstant(tree_node *reg);
/// EmitRegisterConstantWithCast - Utility that casts the value returned by
/// EmitRegisterConstant to the given register type.
llvm::Constant *EmitRegisterConstantWithCast(tree_node *reg, tree_node *type);
/// EmitComplexRegisterConstant - Turn the given COMPLEX_CST into an LLVM
/// constant of the corresponding register type.
llvm::Constant *EmitComplexRegisterConstant(tree_node *reg);
/// EmitIntegerRegisterConstant - Turn the given INTEGER_CST into an LLVM
/// constant of the corresponding register type.
llvm::Constant *EmitIntegerRegisterConstant(tree_node *reg);
/// EmitRealRegisterConstant - Turn the given REAL_CST into an LLVM constant
/// of the corresponding register type.
llvm::Constant *EmitRealRegisterConstant(tree_node *reg);
/// EmitConstantVectorConstructor - Turn the given constant CONSTRUCTOR into
/// an LLVM constant of the corresponding vector register type.
llvm::Constant *EmitConstantVectorConstructor(tree_node *reg);
/// EmitVectorRegisterConstant - Turn the given VECTOR_CST into an LLVM
/// constant of the corresponding register type.
llvm::Constant *EmitVectorRegisterConstant(tree_node *reg);
/// EmitMemory - Convert the specified gimple register or local constant of
/// register type to an LLVM value with in-memory type (given by ConvertType).
/// TODO: Eliminate this method, see Mem2Reg and Reg2Mem above.
llvm::Value *EmitMemory(tree_node *reg);
/// VectorHighElements - Return a vector of half the length, consisting of the
/// elements of the given vector with indices in the top half.
llvm::Value *VectorHighElements(llvm::Value *Vec);
/// VectorLowElements - Return a vector of half the length, consisting of the
/// elements of the given vector with indices in the bottom half.
llvm::Value *VectorLowElements(llvm::Value *Vec);
private:
// Optional target defined builtin intrinsic expanding function.
bool TargetIntrinsicLower(gimple_statement_d *stmt, tree_node *fndecl,
const MemRef *DestLoc, llvm::Value *&Result,
llvm::Type *ResultType,
std::vector<llvm::Value *> &Ops);
public:
// Helper for taking the address of a label.
llvm::Constant *AddressOfLABEL_DECL(tree_node *exp);
};
#endif /* DRAGONEGG_INTERNALS_H */