[llvm-commits] [dragonegg] r93239 - in /dragonegg/trunk: llvm-convert.cpp llvm-internal.h
Duncan Sands
baldrick at free.fr
Tue Jan 12 08:44:03 PST 2010
Author: baldrick
Date: Tue Jan 12 10:44:01 2010
New Revision: 93239
URL: http://llvm.org/viewvc/llvm-project?rev=93239&view=rev
Log:
Reorder some function bodies and tweak some names. No
functionality change intended.
Modified:
dragonegg/trunk/llvm-convert.cpp
dragonegg/trunk/llvm-internal.h
Modified: dragonegg/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-convert.cpp?rev=93239&r1=93238&r2=93239&view=diff
==============================================================================
--- dragonegg/trunk/llvm-convert.cpp (original)
+++ dragonegg/trunk/llvm-convert.cpp Tue Jan 12 10:44:01 2010
@@ -910,7 +910,7 @@
Function *TreeToLLVM::FinishFunctionBody() {
// Insert the return block at the end of the function.
- EmitBlock(ReturnBB);
+ BeginBlock(ReturnBB);
SmallVector <Value *, 4> RetVals;
@@ -1053,7 +1053,7 @@
// Avoid outputting a pointless branch at the end of the entry block.
if (bb != ENTRY_BLOCK_PTR)
- EmitBlock(getBasicBlock(bb));
+ BeginBlock(getBasicBlock(bb));
// Create an LLVM phi node for each GCC phi and define the associated ssa name
// using it. Do not populate with operands at this point since some ssa names
@@ -1357,9 +1357,9 @@
return MemRef(AI, AI->getAlignment(), false);
}
-/// EmitBlock - Add the specified basic block to the end of the function. If
+/// 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 TreeToLLVM::EmitBlock(BasicBlock *BB) {
+void TreeToLLVM::BeginBlock(BasicBlock *BB) {
BasicBlock *CurBB = Builder.GetInsertBlock();
// If the previous block falls through to BB, add an explicit branch.
if (CurBB->getTerminator() == 0) {
@@ -1531,7 +1531,6 @@
}
/// EmitAggregateZero - Zero the elements of DestLoc.
-///
void TreeToLLVM::EmitAggregateZero(MemRef DestLoc, tree type) {
// If the type is small, copy the elements instead of using a block copy.
if (TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST &&
@@ -1822,7 +1821,7 @@
CreateExceptionValues();
- EmitBlock(LandingPad);
+ BeginBlock(LandingPad);
// Fetch and store the exception.
Value *Ex = Builder.CreateCall(FuncEHException, "eh_ptr");
@@ -1928,7 +1927,7 @@
CreateExceptionValues();
- EmitBlock(PostPad);
+ BeginBlock(PostPad);
abort();//FIXME
//FIXME eh_region region = get_eh_region(i);
@@ -1951,7 +1950,7 @@
//FIXME // Branch on the compare.
//FIXME BasicBlock *NoFilterBB = BasicBlock::Create(Context, "nofilter");
//FIXME Builder.CreateCondBr(Compare, Dest, NoFilterBB);
-//FIXME EmitBlock(NoFilterBB);
+//FIXME BeginBlock(NoFilterBB);
//FIXME } else if (RegionKind > 0) {
//FIXME // Catch
//FIXME tree TypeList = get_eh_type_list(region);
@@ -1997,7 +1996,7 @@
//FIXME NoCatchBB = BasicBlock::Create(Context, "nocatch");
//FIXME // Branch on the compare.
//FIXME Builder.CreateCondBr(Cond, Dest, NoCatchBB);
-//FIXME EmitBlock(NoCatchBB);
+//FIXME BeginBlock(NoCatchBB);
//FIXME }
//FIXME
//FIXME // Emit a RESX_EXPR which skips handlers with no post landing pad.
@@ -2035,7 +2034,7 @@
void TreeToLLVM::EmitUnwindBlock() {
if (UnwindBB) {
CreateExceptionValues();
- EmitBlock(UnwindBB);
+ BeginBlock(UnwindBB);
abort();//FIXME
//FIXME // Fetch and store exception handler.
//FIXME Value *Arg = Builder.CreateLoad(ExceptionValue, "eh_ptr");
@@ -2080,170 +2079,6 @@
return false;
}
-/// EmitSSA_NAME - Return the defining value of the given SSA_NAME.
-/// Only creates code in the entry block.
-Value *TreeToLLVM::EmitSSA_NAME(tree reg) {
- assert(TREE_CODE(reg) == SSA_NAME && "Expected an SSA name!");
- assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!");
-
- // If we already found the definition of the SSA name, return it.
- if (Value *ExistingValue = SSANames[reg]) {
- assert(ExistingValue->getType() == ConvertType(TREE_TYPE(reg)) &&
- "SSA name has wrong type!");
- if (!isSSAPlaceholder(ExistingValue))
- return ExistingValue;
- }
-
- // If this is not the definition of the SSA name, return a placeholder value.
- if (!SSA_NAME_IS_DEFAULT_DEF(reg)) {
- if (Value *ExistingValue = SSANames[reg])
- return ExistingValue;
- return SSANames[reg] = GetSSAPlaceholder(ConvertType(TREE_TYPE(reg)));
- }
-
- // This SSA name is the default definition for the underlying symbol.
-
- // The underlying symbol is an SSA variable.
- tree var = SSA_NAME_VAR(reg);
- assert(SSA_VAR_P(var) && "Not an SSA variable!");
-
- // If the variable is itself an ssa name, use its LLVM value.
- if (TREE_CODE (var) == SSA_NAME) {
- Value *Val = EmitSSA_NAME(var);
- assert(Val->getType() == ConvertType(TREE_TYPE(reg)) &&
- "SSA name has wrong type!");
- return DefineSSAName(reg, Val);
- }
-
- // Otherwise the symbol is a VAR_DECL, PARM_DECL or RESULT_DECL. Since a
- // default definition is only created if the very first reference to the
- // variable in the function is a read operation, and refers to the value
- // read, it has an undefined value except for PARM_DECLs.
- if (TREE_CODE(var) != PARM_DECL)
- return DefineSSAName(reg, UndefValue::get(ConvertType(TREE_TYPE(reg))));
-
- // Read the initial value of the parameter and associate it with the ssa name.
- assert(DECL_LOCAL_IF_SET(var) && "Parameter not laid out?");
-
- unsigned Alignment = DECL_ALIGN(var);
- assert(Alignment != 0 && "Parameter with unknown alignment!");
-
- const Type *Ty = ConvertType(TREE_TYPE(reg));
-
- // Perform the load in the entry block, after all parameters have been set up
- // with their initial values, and before any modifications to their values.
- LoadInst *LI = new LoadInst(DECL_LOCAL_IF_SET(var), "", SSAInsertionPoint);
- LI->setAlignment(Alignment);
-
- // Potentially perform a useless type conversion (useless_type_conversion_p).
- Value *Def = LI;
- if (LI->getType() != Ty)
- Def = new BitCastInst(Def, Ty, "", SSAInsertionPoint);
- if (flag_verbose_asm)
- NameValue(Def, reg);
- return DefineSSAName(reg, Def);
-}
-
-/// EmitInvariantAddress - The given address is constant in this function.
-/// Return the corresponding LLVM value. Only creates code in the entry block.
-Value *TreeToLLVM::EmitInvariantAddress(tree addr) {
- assert(is_gimple_invariant_address(addr) &&
- "Expected a locally constant address!");
- assert(is_gimple_reg_type(TREE_TYPE(addr)) && "Not of register type!");
-
- // Any generated code goes in the entry block.
- BasicBlock *EntryBlock = Fn->begin();
-
- // Note the current builder position.
- BasicBlock *SavedInsertBB = Builder.GetInsertBlock();
- BasicBlock::iterator SavedInsertPoint = Builder.GetInsertPoint();
-
- // Pop the entry block terminator. There may not be a terminator if we are
- // recursing or if the entry block was not yet finished.
- Instruction *Terminator = EntryBlock->getTerminator();
- assert(((SavedInsertBB != EntryBlock && Terminator) ||
- (SavedInsertPoint == EntryBlock->end() && !Terminator)) &&
- "Insertion point doesn't make sense!");
- if (Terminator)
- Terminator->removeFromParent();
-
- // Point the builder at the end of the entry block.
- Builder.SetInsertPoint(EntryBlock);
-
- // Calculate the address.
- assert(TREE_CODE(addr) == ADDR_EXPR && "Invariant address not ADDR_EXPR!");
- Value *Address = EmitADDR_EXPR(addr);
-
- // Restore the entry block terminator.
- if (Terminator)
- EntryBlock->getInstList().push_back(Terminator);
-
- // Restore the builder insertion point.
- if (SavedInsertBB != EntryBlock)
- Builder.SetInsertPoint(SavedInsertBB, SavedInsertPoint);
-
- assert(Address->getType() == ConvertType(TREE_TYPE(addr)) &&
- "Invariant address has wrong type!");
- return Address;
-}
-
-/// EmitRegisterConstant - Convert the given global constant of register type to
-/// an LLVM constant. Creates no code, only constants.
-Constant *TreeToLLVM::EmitRegisterConstant(tree reg) {
-#ifndef NDEBUG
- if (!is_gimple_constant(reg)) {
- debug_tree(reg);
- llvm_unreachable("Not a gimple constant!");
- }
-#endif
- assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!");
-
- Constant *C;
- switch (TREE_CODE(reg)) {
- default:
- debug_tree(reg);
- llvm_unreachable("Unhandled GIMPLE constant!");
-
- case INTEGER_CST:
- C = TreeConstantToLLVM::ConvertINTEGER_CST(reg);
- break;
- case REAL_CST:
- C = TreeConstantToLLVM::ConvertREAL_CST(reg);
- break;
- case COMPLEX_CST:
- C = TreeConstantToLLVM::ConvertCOMPLEX_CST(reg);
- break;
- case VECTOR_CST:
- C = TreeConstantToLLVM::ConvertVECTOR_CST(reg);
- break;
- case CONSTRUCTOR:
- C = TreeConstantToLLVM::ConvertCONSTRUCTOR(reg);
- break;
- }
- assert(C->getType() == ConvertType(TREE_TYPE(reg)) &&
- "Constant has wrong type!");
- return C;
-}
-
-/// EmitMinInvariant - The given value is constant in this function. Return the
-/// corresponding LLVM value. Only creates code in the entry block.
-Value *TreeToLLVM::EmitMinInvariant(tree reg) {
- Value *V = (TREE_CODE(reg) == ADDR_EXPR) ?
- EmitInvariantAddress(reg) : EmitRegisterConstant(reg);
- assert(V->getType() == ConvertType(TREE_TYPE(reg)) &&
- "Gimple min invariant has wrong type!");
- return V;
-}
-
-/// EmitRegister - Convert the specified gimple register or local constant of
-/// register type to an LLVM value. Only creates code in the entry block.
-Value *TreeToLLVM::EmitRegister(tree reg) {
- while (TREE_CODE(reg) == OBJ_TYPE_REF) reg = OBJ_TYPE_REF_EXPR(reg);
- Value *V = (TREE_CODE(reg) == SSA_NAME) ?
- EmitSSA_NAME(reg) : EmitMinInvariant(reg);
- return Builder.CreateBitCast(V, ConvertType(TREE_TYPE(reg)));
-}
-
/// EmitLoadOfLValue - When an l-value expression is used in a context that
/// requires an r-value, this method emits the lvalue computation, then loads
/// the result.
@@ -2442,280 +2277,75 @@
return 0;
}
-Value *TreeToLLVM::EmitGimpleAssignSingleRHS(tree rhs) {
- assert(!AGGREGATE_TYPE_P(TREE_TYPE(rhs)) && "Expected a scalar type!");
-
- Value *Result = 0;
+/// llvm_load_scalar_argument - Load value located at LOC.
+static Value *llvm_load_scalar_argument(Value *L,
+ const llvm::Type *LLVMTy,
+ unsigned RealSize,
+ LLVMBuilder &Builder) {
+ if (!RealSize)
+ return UndefValue::get(LLVMTy);
- switch (TREE_CODE(rhs)) {
- default: Result = EmitRegister(rhs); break;
+ // Not clear what this is supposed to do on big endian machines...
+ assert(!BYTES_BIG_ENDIAN && "Unsupported case - please report");
+ assert(isa<IntegerType>(LLVMTy) && "Expected an integer value!");
+ const Type *LoadType = IntegerType::get(Context, RealSize * 8);
+ L = Builder.CreateBitCast(L, LoadType->getPointerTo());
+ Value *Val = Builder.CreateLoad(L);
+ if (LoadType->getPrimitiveSizeInBits() >= LLVMTy->getPrimitiveSizeInBits())
+ Val = Builder.CreateTrunc(Val, LLVMTy);
+ else
+ Val = Builder.CreateZExt(Val, LLVMTy);
+ return Val;
+}
- // Exception handling.
-//FIXME case EXC_PTR_EXPR: Result = EmitEXC_PTR_EXPR(rhs); break;
-//FIXME case FILTER_EXPR: Result = EmitFILTER_EXPR(rhs); break;
+#ifndef LLVM_LOAD_SCALAR_ARGUMENT
+#define LLVM_LOAD_SCALAR_ARGUMENT(LOC,TY,SIZE,BUILDER) \
+ llvm_load_scalar_argument((LOC),(TY),(SIZE),(BUILDER))
+#endif
- // References (tcc_reference).
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
- case BIT_FIELD_REF:
- case COMPONENT_REF:
- case IMAGPART_EXPR:
- case INDIRECT_REF:
- case REALPART_EXPR:
- case VIEW_CONVERT_EXPR:
- // Declarations (tcc_declaration).
- case PARM_DECL:
- case RESULT_DECL:
- case VAR_DECL:
- // Constants (tcc_constant).
- case STRING_CST:
- Result = EmitLoadOfLValue(rhs);
- break;
+namespace {
+ /// FunctionCallArgumentConversion - This helper class is driven by the ABI
+ /// definition for this target to figure out how to pass arguments into the
+ /// stack/regs for a function call.
+ struct FunctionCallArgumentConversion : public DefaultABIClient {
+ SmallVector<Value*, 16> &CallOperands;
+ SmallVector<Value*, 2> LocStack;
+ const FunctionType *FTy;
+ const MemRef *DestLoc;
+ bool useReturnSlot;
+ LLVMBuilder &Builder;
+ Value *TheValue;
+ MemRef RetBuf;
+ CallingConv::ID &CallingConv;
+ bool isShadowRet;
+ bool isAggrRet;
+ unsigned Offset;
- // Expressions (tcc_expression).
- case ADDR_EXPR: Result = EmitADDR_EXPR(rhs); break;
- case OBJ_TYPE_REF: Result = EmitOBJ_TYPE_REF(rhs); break;
+ FunctionCallArgumentConversion(SmallVector<Value*, 16> &ops,
+ const FunctionType *FnTy,
+ const MemRef *destloc,
+ bool ReturnSlotOpt,
+ LLVMBuilder &b,
+ CallingConv::ID &CC)
+ : CallOperands(ops), FTy(FnTy), DestLoc(destloc),
+ useReturnSlot(ReturnSlotOpt), Builder(b), CallingConv(CC),
+ isShadowRet(false), isAggrRet(false), Offset(0) { }
- // Exceptional (tcc_exceptional).
- case CONSTRUCTOR: Result = EmitCONSTRUCTOR(rhs, 0); break;
- }
+ /// getCallingConv - This provides the desired CallingConv for the function.
+ CallingConv::ID& getCallingConv(void) { return CallingConv; }
- // Check that the type of the result matches that of the tree node.
- assert(Result && "Expected a scalar, got an aggregate!");
- assert(Result->getType() == ConvertType(TREE_TYPE(rhs)) &&
- "Value has wrong type!");
- return Result;
-}
+ // Push the address of an argument.
+ void pushAddress(Value *Loc) {
+ assert(Loc && "Invalid location!");
+ LocStack.push_back(Loc);
+ }
-Value *TreeToLLVM::EmitGimpleAssignRHS(gimple stmt) {
- if (get_gimple_rhs_class(gimple_expr_code(stmt)) == GIMPLE_SINGLE_RHS)
- return EmitGimpleAssignSingleRHS(gimple_assign_rhs1 (stmt));
-
- tree type = TREE_TYPE(gimple_assign_lhs(stmt));
- tree_code code = gimple_assign_rhs_code(stmt);
- tree rhs1 = gimple_assign_rhs1(stmt);
- tree rhs2 = gimple_assign_rhs2(stmt);
-
- switch (code) {
- default:
- dump(stmt);
- llvm_unreachable("Unhandled GIMPLE assignment!");
-
- // Unary expressions.
- case ABS_EXPR:
- return EmitABS_EXPR(rhs1);
- case BIT_NOT_EXPR:
- return EmitBIT_NOT_EXPR(rhs1);
- case CONJ_EXPR:
- return EmitCONJ_EXPR(rhs1);
- case CONVERT_EXPR:
- case FIX_TRUNC_EXPR:
- case FLOAT_EXPR:
- return EmitCONVERT_EXPR(type, rhs1);
- case NEGATE_EXPR:
- return EmitNEGATE_EXPR(rhs1);
- case NOP_EXPR:
- return EmitNOP_EXPR(type, rhs1);
- case PAREN_EXPR:
- return EmitPAREN_EXPR(rhs1);
- case TRUTH_NOT_EXPR:
- return EmitTRUTH_NOT_EXPR(type, rhs1);
-
- // Comparisons.
- case EQ_EXPR:
- case GE_EXPR:
- case GT_EXPR:
- case LE_EXPR:
- case LT_EXPR:
- case LTGT_EXPR:
- case NE_EXPR:
- case ORDERED_EXPR:
- case UNEQ_EXPR:
- case UNGE_EXPR:
- case UNGT_EXPR:
- case UNLE_EXPR:
- case UNLT_EXPR:
- case UNORDERED_EXPR:
- // The GCC result may be of any integer type.
- return Builder.CreateZExt(EmitCompare(rhs1, rhs2, code), ConvertType(type));
-
- // Binary expressions.
- case BIT_AND_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, Instruction::And);
- case BIT_IOR_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, Instruction::Or);
- case BIT_XOR_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, Instruction::Xor);
- case CEIL_DIV_EXPR:
- return EmitCEIL_DIV_EXPR(type, rhs1, rhs2);
- case COMPLEX_EXPR:
- return EmitCOMPLEX_EXPR(rhs1, rhs2);
- case EXACT_DIV_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
- Instruction::UDiv : Instruction::SDiv);
- case FLOOR_DIV_EXPR:
- return EmitFLOOR_DIV_EXPR(type, rhs1, rhs2);
- case FLOOR_MOD_EXPR:
- return EmitFLOOR_MOD_EXPR(type, rhs1, rhs2);
- case LROTATE_EXPR:
- return EmitRotateOp(type, rhs1, rhs2, Instruction::Shl, Instruction::LShr);
- case LSHIFT_EXPR:
- return EmitShiftOp(rhs1, rhs2, Instruction::Shl);
- case MAX_EXPR:
- return EmitMinMaxExpr(type, rhs1, rhs2, ICmpInst::ICMP_UGE,
- ICmpInst::ICMP_SGE, FCmpInst::FCMP_OGE, true);
- case MIN_EXPR:
- return EmitMinMaxExpr(type, rhs1, rhs2, ICmpInst::ICMP_ULE,
- ICmpInst::ICMP_SLE, FCmpInst::FCMP_OLE, false);
- case MINUS_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, FLOAT_TYPE_P(type) ?
- Instruction::FSub : Instruction::Sub);
- case MULT_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, FLOAT_TYPE_P(type) ?
- Instruction::FMul : Instruction::Mul);
- case PLUS_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, FLOAT_TYPE_P(type) ?
- Instruction::FAdd : Instruction::Add);
- case POINTER_PLUS_EXPR:
- return EmitPOINTER_PLUS_EXPR(type, rhs1, rhs2);
- case RDIV_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, Instruction::FDiv);
- case ROUND_DIV_EXPR:
- return EmitROUND_DIV_EXPR(type, rhs1, rhs2);
- case RROTATE_EXPR:
- return EmitRotateOp(type, rhs1, rhs2, Instruction::LShr, Instruction::Shl);
- case RSHIFT_EXPR:
- return EmitShiftOp(rhs1, rhs2, TYPE_UNSIGNED(type) ?
- Instruction::LShr : Instruction::AShr);
- case TRUNC_DIV_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
- Instruction::UDiv : Instruction::SDiv);
- case TRUNC_MOD_EXPR:
- return EmitBinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
- Instruction::URem : Instruction::SRem);
- case TRUTH_AND_EXPR:
- return EmitTruthOp(type, rhs1, rhs2, Instruction::And);
- case TRUTH_OR_EXPR:
- return EmitTruthOp(type, rhs1, rhs2, Instruction::Or);
- case TRUTH_XOR_EXPR:
- return EmitTruthOp(type, rhs1, rhs2, Instruction::Xor);
- }
-}
-
-Value *TreeToLLVM::EmitGimpleCallRHS(gimple stmt, const MemRef *DestLoc) {
- // Check for a built-in function call. If we can lower it directly, do so
- // now.
- tree fndecl = gimple_call_fndecl(stmt);
- if (fndecl && DECL_BUILT_IN(fndecl) &&
- DECL_BUILT_IN_CLASS(fndecl) != BUILT_IN_FRONTEND) {
- Value *Res = 0;
- if (EmitBuiltinCall(stmt, fndecl, DestLoc, Res))
- return Res;
- }
-
- tree call_expr = gimple_call_fn(stmt);
- assert(TREE_TYPE (call_expr) &&
- (TREE_CODE(TREE_TYPE (call_expr)) == POINTER_TYPE ||
- TREE_CODE(TREE_TYPE (call_expr)) == REFERENCE_TYPE)
- && "Not calling a function pointer?");
-
- tree function_type = TREE_TYPE(TREE_TYPE (call_expr));
- Value *Callee = EmitRegister(call_expr);
- CallingConv::ID CallingConv;
- AttrListPtr PAL;
-
- const Type *Ty =
- TheTypeConverter->ConvertFunctionType(function_type,
- fndecl,
- gimple_call_chain(stmt),
- CallingConv, PAL);
-
- // If this is a direct call to a function using a static chain then we need
- // to ensure the function type is the one just calculated: it has an extra
- // parameter for the chain.
- Callee = Builder.CreateBitCast(Callee, Ty->getPointerTo());
-
- Value *Result = EmitCallOf(Callee, stmt, DestLoc, PAL);
-
- // When calling a "noreturn" function output an unreachable instruction right
- // after the function to prevent LLVM from thinking that control flow will
- // fall into the subsequent block.
- if (gimple_call_flags(stmt) & ECF_NORETURN) {
- Builder.CreateUnreachable();
- EmitBlock(BasicBlock::Create(Context));
- }
- return Result;
-}
-
-/// llvm_load_scalar_argument - Load value located at LOC.
-static Value *llvm_load_scalar_argument(Value *L,
- const llvm::Type *LLVMTy,
- unsigned RealSize,
- LLVMBuilder &Builder) {
- if (!RealSize)
- return UndefValue::get(LLVMTy);
-
- // Not clear what this is supposed to do on big endian machines...
- assert(!BYTES_BIG_ENDIAN && "Unsupported case - please report");
- assert(isa<IntegerType>(LLVMTy) && "Expected an integer value!");
- const Type *LoadType = IntegerType::get(Context, RealSize * 8);
- L = Builder.CreateBitCast(L, LoadType->getPointerTo());
- Value *Val = Builder.CreateLoad(L);
- if (LoadType->getPrimitiveSizeInBits() >= LLVMTy->getPrimitiveSizeInBits())
- Val = Builder.CreateTrunc(Val, LLVMTy);
- else
- Val = Builder.CreateZExt(Val, LLVMTy);
- return Val;
-}
-
-#ifndef LLVM_LOAD_SCALAR_ARGUMENT
-#define LLVM_LOAD_SCALAR_ARGUMENT(LOC,TY,SIZE,BUILDER) \
- llvm_load_scalar_argument((LOC),(TY),(SIZE),(BUILDER))
-#endif
-
-namespace {
- /// FunctionCallArgumentConversion - This helper class is driven by the ABI
- /// definition for this target to figure out how to pass arguments into the
- /// stack/regs for a function call.
- struct FunctionCallArgumentConversion : public DefaultABIClient {
- SmallVector<Value*, 16> &CallOperands;
- SmallVector<Value*, 2> LocStack;
- const FunctionType *FTy;
- const MemRef *DestLoc;
- bool useReturnSlot;
- LLVMBuilder &Builder;
- Value *TheValue;
- MemRef RetBuf;
- CallingConv::ID &CallingConv;
- bool isShadowRet;
- bool isAggrRet;
- unsigned Offset;
-
- FunctionCallArgumentConversion(SmallVector<Value*, 16> &ops,
- const FunctionType *FnTy,
- const MemRef *destloc,
- bool ReturnSlotOpt,
- LLVMBuilder &b,
- CallingConv::ID &CC)
- : CallOperands(ops), FTy(FnTy), DestLoc(destloc),
- useReturnSlot(ReturnSlotOpt), Builder(b), CallingConv(CC),
- isShadowRet(false), isAggrRet(false), Offset(0) { }
-
- /// getCallingConv - This provides the desired CallingConv for the function.
- CallingConv::ID& getCallingConv(void) { return CallingConv; }
-
- // Push the address of an argument.
- void pushAddress(Value *Loc) {
- assert(Loc && "Invalid location!");
- LocStack.push_back(Loc);
- }
-
- // Push the value of an argument.
- void pushValue(Value *V) {
- assert(LocStack.empty() && "Value only allowed at top level!");
- LocStack.push_back(NULL);
- TheValue = V;
- }
+ // Push the value of an argument.
+ void pushValue(Value *V) {
+ assert(LocStack.empty() && "Value only allowed at top level!");
+ LocStack.push_back(NULL);
+ TheValue = V;
+ }
// Get the address of the current location.
Value *getAddress(void) {
@@ -3061,7 +2691,7 @@
CallOperands.begin(), CallOperands.end());
cast<InvokeInst>(Call)->setCallingConv(CallingConvention);
cast<InvokeInst>(Call)->setAttributes(PAL);
- EmitBlock(NextBlock);
+ BeginBlock(NextBlock);
}
if (Client.isShadowReturn())
@@ -4665,7 +4295,7 @@
Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::trap));
// Emit an explicit unreachable instruction.
Builder.CreateUnreachable();
- EmitBlock(BasicBlock::Create(Context));
+ BeginBlock(BasicBlock::Create(Context));
return true;
//TODO // Convert annotation built-in to llvm.annotation intrinsic.
@@ -5690,7 +5320,7 @@
Builder.CreateCall(Intrinsic::getDeclaration(TheModule, IID),
Args.begin(), Args.end());
Result = Builder.CreateUnreachable();
- EmitBlock(BasicBlock::Create(Context));
+ BeginBlock(BasicBlock::Create(Context));
return true;
}
@@ -6497,90 +6127,581 @@
}
}
- const Type *Ty = ConvertType(TREE_TYPE(exp));
- // If we have "extern void foo", make the global have type {} instead of
- // type void.
- if (Ty->isVoidTy()) Ty = StructType::get(Context);
- const PointerType *PTy = Ty->getPointerTo();
- unsigned Alignment = Ty->isSized() ? TD.getABITypeAlignment(Ty) : 1;
- if (DECL_ALIGN(exp)) {
- if (DECL_USER_ALIGN(exp) || 8 * Alignment < (unsigned)DECL_ALIGN(exp))
- Alignment = DECL_ALIGN(exp) / 8;
+ const Type *Ty = ConvertType(TREE_TYPE(exp));
+ // If we have "extern void foo", make the global have type {} instead of
+ // type void.
+ if (Ty->isVoidTy()) Ty = StructType::get(Context);
+ const PointerType *PTy = Ty->getPointerTo();
+ unsigned Alignment = Ty->isSized() ? TD.getABITypeAlignment(Ty) : 1;
+ if (DECL_ALIGN(exp)) {
+ if (DECL_USER_ALIGN(exp) || 8 * Alignment < (unsigned)DECL_ALIGN(exp))
+ Alignment = DECL_ALIGN(exp) / 8;
+ }
+
+ return LValue(Builder.CreateBitCast(Decl, PTy), Alignment);
+}
+
+LValue TreeToLLVM::EmitLV_EXC_PTR_EXPR(tree exp) {
+ CreateExceptionValues();
+ // Cast the address pointer to the expected type.
+ unsigned Alignment = TD.getABITypeAlignment(cast<PointerType>(ExceptionValue->
+ getType())->getElementType());
+ return LValue(Builder.CreateBitCast(ExceptionValue,
+ PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))),
+ Alignment);
+}
+
+LValue TreeToLLVM::EmitLV_FILTER_EXPR(tree exp) {
+ CreateExceptionValues();
+ unsigned Alignment =
+ TD.getABITypeAlignment(cast<PointerType>(ExceptionSelectorValue->
+ getType())->getElementType());
+ return LValue(ExceptionSelectorValue, Alignment);
+}
+
+LValue TreeToLLVM::EmitLV_INDIRECT_REF(tree exp) {
+ // The lvalue is just the address.
+ LValue LV = LValue(EmitRegister(TREE_OPERAND(exp, 0)), expr_align(exp) / 8);
+ // May need a useless type conversion (useless_type_conversion_p), for example
+ // when INDIRECT_REF is applied to a void*, resulting in a non-void type.
+ LV.Ptr = Builder.CreateBitCast(LV.Ptr,
+ ConvertType(TREE_TYPE(exp))->getPointerTo());
+ return LV;
+}
+
+LValue TreeToLLVM::EmitLV_VIEW_CONVERT_EXPR(tree exp) {
+ // The address is the address of the operand.
+ LValue LV = EmitLV(TREE_OPERAND(exp, 0));
+ // The type is the type of the expression.
+ LV.Ptr = Builder.CreateBitCast(LV.Ptr,
+ ConvertType(TREE_TYPE(exp))->getPointerTo());
+ return LV;
+}
+
+LValue TreeToLLVM::EmitLV_WITH_SIZE_EXPR(tree exp) {
+ // The address is the address of the operand.
+ return EmitLV(TREE_OPERAND(exp, 0));
+}
+
+LValue TreeToLLVM::EmitLV_XXXXPART_EXPR(tree exp, unsigned Idx) {
+ LValue Ptr = EmitLV(TREE_OPERAND(exp, 0));
+ assert(!Ptr.isBitfield() &&
+ "REALPART_EXPR / IMAGPART_EXPR operands cannot be bitfields!");
+ unsigned Alignment;
+ if (Idx == 0)
+ // REALPART alignment is same as the complex operand.
+ Alignment = Ptr.getAlignment();
+ else
+ // IMAGPART alignment = MinAlign(Ptr.Alignment, sizeof field);
+ Alignment = MinAlign(Ptr.getAlignment(),
+ TD.getTypeAllocSize(Ptr.Ptr->getType()));
+ return LValue(Builder.CreateStructGEP(Ptr.Ptr, Idx), Alignment);
+}
+
+LValue TreeToLLVM::EmitLV_SSA_NAME(tree exp) {
+ // TODO: Check the ssa name is being used as an rvalue, see EmitLoadOfLValue.
+ Value *Temp = CreateTemporary(ConvertType(TREE_TYPE(exp)));
+ Builder.CreateStore(EmitSSA_NAME(exp), Temp);
+ return LValue(Temp, 1);
+}
+
+Constant *TreeToLLVM::EmitLV_LABEL_DECL(tree exp) {
+ return BlockAddress::get(Fn, getLabelDeclBlock(exp));
+}
+
+
+//===----------------------------------------------------------------------===//
+// ... Emit helpers ...
+//===----------------------------------------------------------------------===//
+
+/// EmitMinInvariant - The given value is constant in this function. Return the
+/// corresponding LLVM value. Only creates code in the entry block.
+Value *TreeToLLVM::EmitMinInvariant(tree reg) {
+ Value *V = (TREE_CODE(reg) == ADDR_EXPR) ?
+ EmitInvariantAddress(reg) : EmitRegisterConstant(reg);
+ assert(V->getType() == ConvertType(TREE_TYPE(reg)) &&
+ "Gimple min invariant has wrong type!");
+ return V;
+}
+
+/// EmitInvariantAddress - The given address is constant in this function.
+/// Return the corresponding LLVM value. Only creates code in the entry block.
+Value *TreeToLLVM::EmitInvariantAddress(tree addr) {
+ assert(is_gimple_invariant_address(addr) &&
+ "Expected a locally constant address!");
+ assert(is_gimple_reg_type(TREE_TYPE(addr)) && "Not of register type!");
+
+ // Any generated code goes in the entry block.
+ BasicBlock *EntryBlock = Fn->begin();
+
+ // Note the current builder position.
+ BasicBlock *SavedInsertBB = Builder.GetInsertBlock();
+ BasicBlock::iterator SavedInsertPoint = Builder.GetInsertPoint();
+
+ // Pop the entry block terminator. There may not be a terminator if we are
+ // recursing or if the entry block was not yet finished.
+ Instruction *Terminator = EntryBlock->getTerminator();
+ assert(((SavedInsertBB != EntryBlock && Terminator) ||
+ (SavedInsertPoint == EntryBlock->end() && !Terminator)) &&
+ "Insertion point doesn't make sense!");
+ if (Terminator)
+ Terminator->removeFromParent();
+
+ // Point the builder at the end of the entry block.
+ Builder.SetInsertPoint(EntryBlock);
+
+ // Calculate the address.
+ assert(TREE_CODE(addr) == ADDR_EXPR && "Invariant address not ADDR_EXPR!");
+ Value *Address = EmitADDR_EXPR(addr);
+
+ // Restore the entry block terminator.
+ if (Terminator)
+ EntryBlock->getInstList().push_back(Terminator);
+
+ // Restore the builder insertion point.
+ if (SavedInsertBB != EntryBlock)
+ Builder.SetInsertPoint(SavedInsertBB, SavedInsertPoint);
+
+ assert(Address->getType() == ConvertType(TREE_TYPE(addr)) &&
+ "Invariant address has wrong type!");
+ return Address;
+}
+
+/// EmitRegisterConstant - Convert the given global constant of register type to
+/// an LLVM constant. Creates no code, only constants.
+Constant *TreeToLLVM::EmitRegisterConstant(tree reg) {
+#ifndef NDEBUG
+ if (!is_gimple_constant(reg)) {
+ debug_tree(reg);
+ llvm_unreachable("Not a gimple constant!");
+ }
+#endif
+ assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!");
+
+ Constant *C;
+ switch (TREE_CODE(reg)) {
+ default:
+ debug_tree(reg);
+ llvm_unreachable("Unhandled GIMPLE constant!");
+
+ case INTEGER_CST:
+ C = TreeConstantToLLVM::ConvertINTEGER_CST(reg);
+ break;
+ case REAL_CST:
+ C = TreeConstantToLLVM::ConvertREAL_CST(reg);
+ break;
+ case COMPLEX_CST:
+ C = TreeConstantToLLVM::ConvertCOMPLEX_CST(reg);
+ break;
+ case VECTOR_CST:
+ C = TreeConstantToLLVM::ConvertVECTOR_CST(reg);
+ break;
+ case CONSTRUCTOR:
+ C = TreeConstantToLLVM::ConvertCONSTRUCTOR(reg);
+ break;
+ }
+ assert(C->getType() == ConvertType(TREE_TYPE(reg)) &&
+ "Constant has wrong type!");
+ return C;
+}
+
+
+//===----------------------------------------------------------------------===//
+// ... Emit* - Convert register expression to LLVM...
+//===----------------------------------------------------------------------===//
+
+/// EmitRegister - Convert the specified gimple register or local constant of
+/// register type to an LLVM value. Only creates code in the entry block.
+Value *TreeToLLVM::EmitRegister(tree reg) {
+ while (TREE_CODE(reg) == OBJ_TYPE_REF) reg = OBJ_TYPE_REF_EXPR(reg);
+ Value *V = (TREE_CODE(reg) == SSA_NAME) ?
+ EmitSSA_NAME(reg) : EmitMinInvariant(reg);
+ return Builder.CreateBitCast(V, ConvertType(TREE_TYPE(reg)));
+}
+
+/// EmitSSA_NAME - Return the defining value of the given SSA_NAME.
+/// Only creates code in the entry block.
+Value *TreeToLLVM::EmitSSA_NAME(tree reg) {
+ assert(TREE_CODE(reg) == SSA_NAME && "Expected an SSA name!");
+ assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!");
+
+ // If we already found the definition of the SSA name, return it.
+ if (Value *ExistingValue = SSANames[reg]) {
+ assert(ExistingValue->getType() == ConvertType(TREE_TYPE(reg)) &&
+ "SSA name has wrong type!");
+ if (!isSSAPlaceholder(ExistingValue))
+ return ExistingValue;
+ }
+
+ // If this is not the definition of the SSA name, return a placeholder value.
+ if (!SSA_NAME_IS_DEFAULT_DEF(reg)) {
+ if (Value *ExistingValue = SSANames[reg])
+ return ExistingValue;
+ return SSANames[reg] = GetSSAPlaceholder(ConvertType(TREE_TYPE(reg)));
+ }
+
+ // This SSA name is the default definition for the underlying symbol.
+
+ // The underlying symbol is an SSA variable.
+ tree var = SSA_NAME_VAR(reg);
+ assert(SSA_VAR_P(var) && "Not an SSA variable!");
+
+ // If the variable is itself an ssa name, use its LLVM value.
+ if (TREE_CODE (var) == SSA_NAME) {
+ Value *Val = EmitSSA_NAME(var);
+ assert(Val->getType() == ConvertType(TREE_TYPE(reg)) &&
+ "SSA name has wrong type!");
+ return DefineSSAName(reg, Val);
+ }
+
+ // Otherwise the symbol is a VAR_DECL, PARM_DECL or RESULT_DECL. Since a
+ // default definition is only created if the very first reference to the
+ // variable in the function is a read operation, and refers to the value
+ // read, it has an undefined value except for PARM_DECLs.
+ if (TREE_CODE(var) != PARM_DECL)
+ return DefineSSAName(reg, UndefValue::get(ConvertType(TREE_TYPE(reg))));
+
+ // Read the initial value of the parameter and associate it with the ssa name.
+ assert(DECL_LOCAL_IF_SET(var) && "Parameter not laid out?");
+
+ unsigned Alignment = DECL_ALIGN(var);
+ assert(Alignment != 0 && "Parameter with unknown alignment!");
+
+ const Type *Ty = ConvertType(TREE_TYPE(reg));
+
+ // Perform the load in the entry block, after all parameters have been set up
+ // with their initial values, and before any modifications to their values.
+ LoadInst *LI = new LoadInst(DECL_LOCAL_IF_SET(var), "", SSAInsertionPoint);
+ LI->setAlignment(Alignment);
+
+ // Potentially perform a useless type conversion (useless_type_conversion_p).
+ Value *Def = LI;
+ if (LI->getType() != Ty)
+ Def = new BitCastInst(Def, Ty, "", SSAInsertionPoint);
+ if (flag_verbose_asm)
+ NameValue(Def, reg);
+ return DefineSSAName(reg, Def);
+}
+
+
+//===----------------------------------------------------------------------===//
+// ... Render helpers ...
+//===----------------------------------------------------------------------===//
+
+/// EmitAssignRHS - Convert the RHS of a scalar GIMPLE_ASSIGN to LLVM.
+Value *TreeToLLVM::EmitAssignRHS(gimple stmt) {
+ // Loads from memory and other non-register expressions are handled by
+ // EmitAssignSingleRHS.
+ if (get_gimple_rhs_class(gimple_expr_code(stmt)) == GIMPLE_SINGLE_RHS)
+ return EmitAssignSingleRHS(gimple_assign_rhs1 (stmt));
+
+ // The RHS is a register expression. Emit it now.
+ tree type = TREE_TYPE(gimple_assign_lhs(stmt));
+ tree_code code = gimple_assign_rhs_code(stmt);
+ tree rhs1 = gimple_assign_rhs1(stmt);
+ tree rhs2 = gimple_assign_rhs2(stmt);
+
+ switch (code) {
+ default:
+ dump(stmt);
+ llvm_unreachable("Unhandled GIMPLE assignment!");
+
+ // Unary expressions.
+ case ABS_EXPR:
+ return EmitABS_EXPR(rhs1);
+ case BIT_NOT_EXPR:
+ return EmitBIT_NOT_EXPR(rhs1);
+ case CONJ_EXPR:
+ return EmitCONJ_EXPR(rhs1);
+ case CONVERT_EXPR:
+ case FIX_TRUNC_EXPR:
+ case FLOAT_EXPR:
+ return EmitCONVERT_EXPR(type, rhs1);
+ case NEGATE_EXPR:
+ return EmitNEGATE_EXPR(rhs1);
+ case NOP_EXPR:
+ return EmitNOP_EXPR(type, rhs1);
+ case PAREN_EXPR:
+ return EmitPAREN_EXPR(rhs1);
+ case TRUTH_NOT_EXPR:
+ return EmitTRUTH_NOT_EXPR(type, rhs1);
+
+ // Comparisons.
+ case EQ_EXPR:
+ case GE_EXPR:
+ case GT_EXPR:
+ case LE_EXPR:
+ case LT_EXPR:
+ case LTGT_EXPR:
+ case NE_EXPR:
+ case ORDERED_EXPR:
+ case UNEQ_EXPR:
+ case UNGE_EXPR:
+ case UNGT_EXPR:
+ case UNLE_EXPR:
+ case UNLT_EXPR:
+ case UNORDERED_EXPR:
+ // The GCC result may be of any integer type.
+ return Builder.CreateZExt(EmitCompare(rhs1, rhs2, code), ConvertType(type));
+
+ // Binary expressions.
+ case BIT_AND_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, Instruction::And);
+ case BIT_IOR_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, Instruction::Or);
+ case BIT_XOR_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, Instruction::Xor);
+ case CEIL_DIV_EXPR:
+ return EmitCEIL_DIV_EXPR(type, rhs1, rhs2);
+ case COMPLEX_EXPR:
+ return EmitCOMPLEX_EXPR(rhs1, rhs2);
+ case EXACT_DIV_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
+ Instruction::UDiv : Instruction::SDiv);
+ case FLOOR_DIV_EXPR:
+ return EmitFLOOR_DIV_EXPR(type, rhs1, rhs2);
+ case FLOOR_MOD_EXPR:
+ return EmitFLOOR_MOD_EXPR(type, rhs1, rhs2);
+ case LROTATE_EXPR:
+ return EmitRotateOp(type, rhs1, rhs2, Instruction::Shl, Instruction::LShr);
+ case LSHIFT_EXPR:
+ return EmitShiftOp(rhs1, rhs2, Instruction::Shl);
+ case MAX_EXPR:
+ return EmitMinMaxExpr(type, rhs1, rhs2, ICmpInst::ICMP_UGE,
+ ICmpInst::ICMP_SGE, FCmpInst::FCMP_OGE, true);
+ case MIN_EXPR:
+ return EmitMinMaxExpr(type, rhs1, rhs2, ICmpInst::ICMP_ULE,
+ ICmpInst::ICMP_SLE, FCmpInst::FCMP_OLE, false);
+ case MINUS_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, FLOAT_TYPE_P(type) ?
+ Instruction::FSub : Instruction::Sub);
+ case MULT_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, FLOAT_TYPE_P(type) ?
+ Instruction::FMul : Instruction::Mul);
+ case PLUS_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, FLOAT_TYPE_P(type) ?
+ Instruction::FAdd : Instruction::Add);
+ case POINTER_PLUS_EXPR:
+ return EmitPOINTER_PLUS_EXPR(type, rhs1, rhs2);
+ case RDIV_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, Instruction::FDiv);
+ case ROUND_DIV_EXPR:
+ return EmitROUND_DIV_EXPR(type, rhs1, rhs2);
+ case RROTATE_EXPR:
+ return EmitRotateOp(type, rhs1, rhs2, Instruction::LShr, Instruction::Shl);
+ case RSHIFT_EXPR:
+ return EmitShiftOp(rhs1, rhs2, TYPE_UNSIGNED(type) ?
+ Instruction::LShr : Instruction::AShr);
+ case TRUNC_DIV_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
+ Instruction::UDiv : Instruction::SDiv);
+ case TRUNC_MOD_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
+ Instruction::URem : Instruction::SRem);
+ case TRUTH_AND_EXPR:
+ return EmitTruthOp(type, rhs1, rhs2, Instruction::And);
+ case TRUTH_OR_EXPR:
+ return EmitTruthOp(type, rhs1, rhs2, Instruction::Or);
+ case TRUTH_XOR_EXPR:
+ return EmitTruthOp(type, rhs1, rhs2, Instruction::Xor);
+ }
+}
+
+/// EmitAssignSingleRHS - Helper for EmitAssignRHS. Handles those RHS that are
+/// not register expressions.
+Value *TreeToLLVM::EmitAssignSingleRHS(tree rhs) {
+ assert(!AGGREGATE_TYPE_P(TREE_TYPE(rhs)) && "Expected a scalar type!");
+
+ switch (TREE_CODE(rhs)) {
+ // Catch-all for SSA names, constants etc.
+ default: return EmitRegister(rhs);
+
+ // Expressions (tcc_expression).
+ case ADDR_EXPR: return EmitADDR_EXPR(rhs);
+ case OBJ_TYPE_REF: return EmitOBJ_TYPE_REF(rhs);
+
+ // Exceptional (tcc_exceptional).
+ case CONSTRUCTOR: return EmitCONSTRUCTOR(rhs, 0);
+
+ // References (tcc_reference).
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case BIT_FIELD_REF:
+ case COMPONENT_REF:
+ case IMAGPART_EXPR:
+ case INDIRECT_REF:
+ case REALPART_EXPR:
+ case VIEW_CONVERT_EXPR:
+ return EmitLoadOfLValue(rhs); // Load from memory.
+
+ // Declarations (tcc_declaration).
+ case PARM_DECL:
+ case RESULT_DECL:
+ case VAR_DECL:
+ return EmitLoadOfLValue(rhs); // Load from memory.
+
+ // Constants (tcc_constant).
+ case STRING_CST:
+ return EmitLoadOfLValue(rhs); // Load from memory.
+ }
+}
+
+/// OutputCallRHS - Convert the RHS of a GIMPLE_CALL.
+Value *TreeToLLVM::OutputCallRHS(gimple stmt, const MemRef *DestLoc) {
+ // Check for a built-in function call. If we can lower it directly, do so
+ // now.
+ tree fndecl = gimple_call_fndecl(stmt);
+ if (fndecl && DECL_BUILT_IN(fndecl) &&
+ DECL_BUILT_IN_CLASS(fndecl) != BUILT_IN_FRONTEND) {
+ Value *Res = 0;
+ if (EmitBuiltinCall(stmt, fndecl, DestLoc, Res))
+ return Res;
+ }
+
+ tree call_expr = gimple_call_fn(stmt);
+ assert(TREE_TYPE (call_expr) &&
+ (TREE_CODE(TREE_TYPE (call_expr)) == POINTER_TYPE ||
+ TREE_CODE(TREE_TYPE (call_expr)) == REFERENCE_TYPE)
+ && "Not calling a function pointer?");
+
+ tree function_type = TREE_TYPE(TREE_TYPE (call_expr));
+ Value *Callee = EmitRegister(call_expr);
+ CallingConv::ID CallingConv;
+ AttrListPtr PAL;
+
+ const Type *Ty =
+ TheTypeConverter->ConvertFunctionType(function_type,
+ fndecl,
+ gimple_call_chain(stmt),
+ CallingConv, PAL);
+
+ // If this is a direct call to a function using a static chain then we need
+ // to ensure the function type is the one just calculated: it has an extra
+ // parameter for the chain.
+ Callee = Builder.CreateBitCast(Callee, Ty->getPointerTo());
+
+ Value *Result = EmitCallOf(Callee, stmt, DestLoc, PAL);
+
+ // When calling a "noreturn" function output an unreachable instruction right
+ // after the function to prevent LLVM from thinking that control flow will
+ // fall into the subsequent block.
+ if (gimple_call_flags(stmt) & ECF_NORETURN) {
+ Builder.CreateUnreachable();
+ BeginBlock(BasicBlock::Create(Context));
+ }
+ return Result;
+}
+
+/// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS.
+void TreeToLLVM::WriteScalarToLHS(tree lhs, Value *RHS) {
+ // Perform a useless type conversion (useless_type_conversion_p).
+ RHS = Builder.CreateBitCast(RHS, ConvertType(TREE_TYPE(lhs)));
+
+ // If this is the definition of an ssa name, record it in the SSANames map.
+ if (TREE_CODE(lhs) == SSA_NAME) {
+ if (flag_verbose_asm)
+ NameValue(RHS, lhs);
+ DefineSSAName(lhs, RHS);
+ return;
+ }
+
+ if (canEmitRegisterVariable(lhs)) {
+ // If this is a store to a register variable, EmitLV can't handle the dest
+ // (there is no l-value of a register variable). Emit an inline asm node
+ // that copies the value into the specified register.
+ EmitModifyOfRegisterVariable(lhs, RHS);
+ return;
+ }
+
+ LValue LV = EmitLV(lhs);
+ bool isVolatile = TREE_THIS_VOLATILE(lhs);
+ unsigned Alignment = LV.getAlignment();
+
+ if (!LV.isBitfield()) {
+ // Non-bitfield, scalar value. Just emit a store.
+ StoreInst *SI = Builder.CreateStore(RHS, LV.Ptr, isVolatile);
+ SI->setAlignment(Alignment);
+ return;
}
- return LValue(Builder.CreateBitCast(Decl, PTy), Alignment);
-}
+ // Last case, this is a store to a bitfield, so we have to emit a
+ // read/modify/write sequence.
-LValue TreeToLLVM::EmitLV_EXC_PTR_EXPR(tree exp) {
- CreateExceptionValues();
- // Cast the address pointer to the expected type.
- unsigned Alignment = TD.getABITypeAlignment(cast<PointerType>(ExceptionValue->
- getType())->getElementType());
- return LValue(Builder.CreateBitCast(ExceptionValue,
- PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))),
- Alignment);
-}
+ if (!LV.BitSize)
+ return;
-LValue TreeToLLVM::EmitLV_FILTER_EXPR(tree exp) {
- CreateExceptionValues();
- unsigned Alignment =
- TD.getABITypeAlignment(cast<PointerType>(ExceptionSelectorValue->
- getType())->getElementType());
- return LValue(ExceptionSelectorValue, Alignment);
-}
+ const Type *ValTy = cast<PointerType>(LV.Ptr->getType())->getElementType();
+ unsigned ValSizeInBits = ValTy->getPrimitiveSizeInBits();
-LValue TreeToLLVM::EmitLV_INDIRECT_REF(tree exp) {
- // The lvalue is just the address.
- LValue LV = LValue(EmitRegister(TREE_OPERAND(exp, 0)), expr_align(exp) / 8);
- // May need a useless type conversion (useless_type_conversion_p), for example
- // when INDIRECT_REF is applied to a void*, resulting in a non-void type.
- LV.Ptr = Builder.CreateBitCast(LV.Ptr,
- ConvertType(TREE_TYPE(exp))->getPointerTo());
- return LV;
-}
+ // The number of stores needed to write the entire bitfield.
+ unsigned Strides = 1 + (LV.BitStart + LV.BitSize - 1) / ValSizeInBits;
-LValue TreeToLLVM::EmitLV_VIEW_CONVERT_EXPR(tree exp) {
- // The address is the address of the operand.
- LValue LV = EmitLV(TREE_OPERAND(exp, 0));
- // The type is the type of the expression.
- LV.Ptr = Builder.CreateBitCast(LV.Ptr,
- ConvertType(TREE_TYPE(exp))->getPointerTo());
- return LV;
-}
+ assert(ValTy->isInteger() && "Invalid bitfield lvalue!");
+ assert(ValSizeInBits > LV.BitStart && "Bad bitfield lvalue!");
+ assert(ValSizeInBits >= LV.BitSize && "Bad bitfield lvalue!");
+ assert(2*ValSizeInBits > LV.BitSize+LV.BitStart && "Bad bitfield lvalue!");
-LValue TreeToLLVM::EmitLV_WITH_SIZE_EXPR(tree exp) {
- // The address is the address of the operand.
- return EmitLV(TREE_OPERAND(exp, 0));
-}
+ bool Signed = !TYPE_UNSIGNED(TREE_TYPE(lhs));
+ RHS = CastToAnyType(RHS, Signed, ValTy, Signed);
-LValue TreeToLLVM::EmitLV_XXXXPART_EXPR(tree exp, unsigned Idx) {
- LValue Ptr = EmitLV(TREE_OPERAND(exp, 0));
- assert(!Ptr.isBitfield() &&
- "REALPART_EXPR / IMAGPART_EXPR operands cannot be bitfields!");
- unsigned Alignment;
- if (Idx == 0)
- // REALPART alignment is same as the complex operand.
- Alignment = Ptr.getAlignment();
- else
- // IMAGPART alignment = MinAlign(Ptr.Alignment, sizeof field);
- Alignment = MinAlign(Ptr.getAlignment(),
- TD.getTypeAllocSize(Ptr.Ptr->getType()));
- return LValue(Builder.CreateStructGEP(Ptr.Ptr, Idx), Alignment);
-}
+ for (unsigned I = 0; I < Strides; I++) {
+ unsigned Index = BYTES_BIG_ENDIAN ? Strides - I - 1 : I; // LSB first
+ unsigned ThisFirstBit = Index * ValSizeInBits;
+ unsigned ThisLastBitPlusOne = ThisFirstBit + ValSizeInBits;
+ if (ThisFirstBit < LV.BitStart)
+ ThisFirstBit = LV.BitStart;
+ if (ThisLastBitPlusOne > LV.BitStart+LV.BitSize)
+ ThisLastBitPlusOne = LV.BitStart+LV.BitSize;
-LValue TreeToLLVM::EmitLV_SSA_NAME(tree exp) {
- // TODO: Check the ssa name is being used as an rvalue, see EmitLoadOfLValue.
- Value *Temp = CreateTemporary(ConvertType(TREE_TYPE(exp)));
- Builder.CreateStore(EmitSSA_NAME(exp), Temp);
- return LValue(Temp, 1);
-}
+ Value *Ptr = Index ?
+ Builder.CreateGEP(LV.Ptr, ConstantInt::get(Type::getInt32Ty(Context), Index)) :
+ LV.Ptr;
+ LoadInst *LI = Builder.CreateLoad(Ptr, isVolatile);
+ LI->setAlignment(Alignment);
+ Value *OldVal = LI;
+ Value *NewVal = RHS;
-Constant *TreeToLLVM::EmitLV_LABEL_DECL(tree exp) {
- return BlockAddress::get(Fn, getLabelDeclBlock(exp));
+ unsigned BitsInVal = ThisLastBitPlusOne - ThisFirstBit;
+ unsigned FirstBitInVal = ThisFirstBit % ValSizeInBits;
+
+ if (BYTES_BIG_ENDIAN)
+ FirstBitInVal = ValSizeInBits-FirstBitInVal-BitsInVal;
+
+ // If not storing into the zero'th bit, shift the Src value to the left.
+ if (FirstBitInVal) {
+ Value *ShAmt = ConstantInt::get(ValTy, FirstBitInVal);
+ NewVal = Builder.CreateShl(NewVal, ShAmt);
+ }
+
+ // Next, if this doesn't touch the top bit, mask out any bits that shouldn't
+ // be set in the result.
+ uint64_t MaskVal = ((1ULL << BitsInVal)-1) << FirstBitInVal;
+ Constant *Mask = ConstantInt::get(Type::getInt64Ty(Context), MaskVal);
+ Mask = Builder.getFolder().CreateTruncOrBitCast(Mask, ValTy);
+
+ if (FirstBitInVal+BitsInVal != ValSizeInBits)
+ NewVal = Builder.CreateAnd(NewVal, Mask);
+
+ // Next, mask out the bits this bit-field should include from the old value.
+ Mask = Builder.getFolder().CreateNot(Mask);
+ OldVal = Builder.CreateAnd(OldVal, Mask);
+
+ // Finally, merge the two together and store it.
+ NewVal = Builder.CreateOr(OldVal, NewVal);
+
+ StoreInst *SI = Builder.CreateStore(NewVal, Ptr, isVolatile);
+ SI->setAlignment(Alignment);
+
+ if (I + 1 < Strides) {
+ Value *ShAmt = ConstantInt::get(ValTy, BitsInVal);
+ RHS = Builder.CreateLShr(RHS, ShAmt);
+ }
+ }
}
+
//===----------------------------------------------------------------------===//
-// ... Convert GIMPLE to LLVM ...
+// ... Render* - Convert GIMPLE to LLVM ...
//===----------------------------------------------------------------------===//
void TreeToLLVM::RenderGIMPLE_ASM(gimple stmt) {
@@ -7028,7 +7149,7 @@
EmitAggregate(gimple_assign_rhs1 (stmt), NewLoc);
return;
}
- WriteScalarToLHS(lhs, EmitGimpleAssignRHS(stmt));
+ WriteScalarToLHS(lhs, EmitAssignRHS(stmt));
}
void TreeToLLVM::RenderGIMPLE_CALL(gimple stmt) {
@@ -7036,24 +7157,24 @@
if (!lhs) {
// The returned value is not used.
if (!AGGREGATE_TYPE_P(gimple_call_return_type(stmt))) {
- EmitGimpleCallRHS(stmt, 0);
+ OutputCallRHS(stmt, 0);
return;
}
// Create a temporary to hold the returned value.
// TODO: Figure out how to avoid creating this temporary and the
// associated useless code that stores the returned value into it.
MemRef Loc = CreateTempLoc(ConvertType(gimple_call_return_type(stmt)));
- EmitGimpleCallRHS(stmt, &Loc);
+ OutputCallRHS(stmt, &Loc);
return;
}
if (AGGREGATE_TYPE_P(TREE_TYPE(lhs))) {
LValue LV = EmitLV(lhs);
MemRef NewLoc(LV.Ptr, LV.getAlignment(), TREE_THIS_VOLATILE(lhs));
- EmitGimpleCallRHS(stmt, &NewLoc);
+ OutputCallRHS(stmt, &NewLoc);
return;
}
- WriteScalarToLHS(lhs, EmitGimpleCallRHS(stmt, 0));
+ WriteScalarToLHS(lhs, OutputCallRHS(stmt, 0));
}
void TreeToLLVM::RenderGIMPLE_COND(gimple stmt) {
@@ -7184,14 +7305,14 @@
// The range is too big to add to the switch - emit an "if".
if (!IfBlock) {
IfBlock = BasicBlock::Create(Context);
- EmitBlock(IfBlock);
+ BeginBlock(IfBlock);
}
Value *Diff = Builder.CreateSub(Index, LowC);
Value *Cond = Builder.CreateICmpULE(Diff,
ConstantInt::get(Context, Range));
BasicBlock *False_Block = BasicBlock::Create(Context);
Builder.CreateCondBr(Cond, Dest, False_Block);
- EmitBlock(False_Block);
+ BeginBlock(False_Block);
}
}
@@ -8386,114 +8507,3 @@
"It's a bitfield reference or we didn't get to the field!");
return FieldPtr;
}
-
-//===----------------------------------------------------------------------===//
-// ... GIMPLE conversion helpers ...
-//===----------------------------------------------------------------------===//
-
-/// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS.
-void TreeToLLVM::WriteScalarToLHS(tree lhs, Value *RHS) {
- // Perform a useless type conversion (useless_type_conversion_p).
- RHS = Builder.CreateBitCast(RHS, ConvertType(TREE_TYPE(lhs)));
-
- // If this is the definition of an ssa name, record it in the SSANames map.
- if (TREE_CODE(lhs) == SSA_NAME) {
- if (flag_verbose_asm)
- NameValue(RHS, lhs);
- DefineSSAName(lhs, RHS);
- return;
- }
-
- if (canEmitRegisterVariable(lhs)) {
- // If this is a store to a register variable, EmitLV can't handle the dest
- // (there is no l-value of a register variable). Emit an inline asm node
- // that copies the value into the specified register.
- EmitModifyOfRegisterVariable(lhs, RHS);
- return;
- }
-
- LValue LV = EmitLV(lhs);
- bool isVolatile = TREE_THIS_VOLATILE(lhs);
- unsigned Alignment = LV.getAlignment();
-
- if (!LV.isBitfield()) {
- // Non-bitfield, scalar value. Just emit a store.
- StoreInst *SI = Builder.CreateStore(RHS, LV.Ptr, isVolatile);
- SI->setAlignment(Alignment);
- return;
- }
-
- // Last case, this is a store to a bitfield, so we have to emit a
- // read/modify/write sequence.
-
- if (!LV.BitSize)
- return;
-
- const Type *ValTy = cast<PointerType>(LV.Ptr->getType())->getElementType();
- unsigned ValSizeInBits = ValTy->getPrimitiveSizeInBits();
-
- // The number of stores needed to write the entire bitfield.
- unsigned Strides = 1 + (LV.BitStart + LV.BitSize - 1) / ValSizeInBits;
-
- assert(ValTy->isInteger() && "Invalid bitfield lvalue!");
- assert(ValSizeInBits > LV.BitStart && "Bad bitfield lvalue!");
- assert(ValSizeInBits >= LV.BitSize && "Bad bitfield lvalue!");
- assert(2*ValSizeInBits > LV.BitSize+LV.BitStart && "Bad bitfield lvalue!");
-
- bool Signed = !TYPE_UNSIGNED(TREE_TYPE(lhs));
- RHS = CastToAnyType(RHS, Signed, ValTy, Signed);
-
- for (unsigned I = 0; I < Strides; I++) {
- unsigned Index = BYTES_BIG_ENDIAN ? Strides - I - 1 : I; // LSB first
- unsigned ThisFirstBit = Index * ValSizeInBits;
- unsigned ThisLastBitPlusOne = ThisFirstBit + ValSizeInBits;
- if (ThisFirstBit < LV.BitStart)
- ThisFirstBit = LV.BitStart;
- if (ThisLastBitPlusOne > LV.BitStart+LV.BitSize)
- ThisLastBitPlusOne = LV.BitStart+LV.BitSize;
-
- Value *Ptr = Index ?
- Builder.CreateGEP(LV.Ptr, ConstantInt::get(Type::getInt32Ty(Context), Index)) :
- LV.Ptr;
- LoadInst *LI = Builder.CreateLoad(Ptr, isVolatile);
- LI->setAlignment(Alignment);
- Value *OldVal = LI;
- Value *NewVal = RHS;
-
- unsigned BitsInVal = ThisLastBitPlusOne - ThisFirstBit;
- unsigned FirstBitInVal = ThisFirstBit % ValSizeInBits;
-
- if (BYTES_BIG_ENDIAN)
- FirstBitInVal = ValSizeInBits-FirstBitInVal-BitsInVal;
-
- // If not storing into the zero'th bit, shift the Src value to the left.
- if (FirstBitInVal) {
- Value *ShAmt = ConstantInt::get(ValTy, FirstBitInVal);
- NewVal = Builder.CreateShl(NewVal, ShAmt);
- }
-
- // Next, if this doesn't touch the top bit, mask out any bits that shouldn't
- // be set in the result.
- uint64_t MaskVal = ((1ULL << BitsInVal)-1) << FirstBitInVal;
- Constant *Mask = ConstantInt::get(Type::getInt64Ty(Context), MaskVal);
- Mask = Builder.getFolder().CreateTruncOrBitCast(Mask, ValTy);
-
- if (FirstBitInVal+BitsInVal != ValSizeInBits)
- NewVal = Builder.CreateAnd(NewVal, Mask);
-
- // Next, mask out the bits this bit-field should include from the old value.
- Mask = Builder.getFolder().CreateNot(Mask);
- OldVal = Builder.CreateAnd(OldVal, Mask);
-
- // Finally, merge the two together and store it.
- NewVal = Builder.CreateOr(OldVal, NewVal);
-
- StoreInst *SI = Builder.CreateStore(NewVal, Ptr, isVolatile);
- SI->setAlignment(Alignment);
-
- if (I + 1 < Strides) {
- Value *ShAmt = ConstantInt::get(ValTy, BitsInVal);
- RHS = Builder.CreateLShr(RHS, ShAmt);
- }
- }
-}
Modified: dragonegg/trunk/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-internal.h?rev=93239&r1=93238&r2=93239&view=diff
==============================================================================
--- dragonegg/trunk/llvm-internal.h (original)
+++ dragonegg/trunk/llvm-internal.h Tue Jan 12 10:44:01 2010
@@ -522,32 +522,11 @@
/// name. Returns the provided value as a convenience.
Value *DefineSSAName(tree_node *reg, Value *Val);
- /// EmitSSA_NAME - Return the defining value of the given SSA_NAME.
- /// Only creates code in the entry block.
- Value *EmitSSA_NAME(tree_node *reg);
-
- /// EmitInvariantAddress - The given address is constant in this function.
- /// Return the corresponding LLVM value. Only creates code in the entry block.
- Value *EmitInvariantAddress(tree_node *addr);
-
- /// EmitRegisterConstant - Convert the given global constant of register type
- /// to an LLVM constant. Creates no code, only constants.
- Constant *EmitRegisterConstant(tree_node *reg);
-
- /// EmitMinInvariant - The given value is constant in this function. Return
- /// the corresponding LLVM value. Only creates code in the entry block.
- Value *EmitMinInvariant(tree_node *reg);
-
- /// EmitRegister - Convert the specified gimple register or local constant of
- /// register type to an LLVM value. Only creates code in the entry block.
- Value *EmitRegister(tree_node *reg);
-
- /// EmitBlock - Add the specified basic block to the end of the function. If
+ /// 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 EmitBlock(BasicBlock *BB);
+ void BeginBlock(BasicBlock *BB);
/// EmitAggregateZero - Zero the elements of DestLoc.
- ///
void EmitAggregateZero(MemRef DestLoc, tree_node *GCCType);
/// EmitMemCpy/EmitMemMove/EmitMemSet - Emit an llvm.memcpy/llvm.memmove or
@@ -577,8 +556,18 @@
BasicBlock *getPostPad(unsigned RegionNo);
private:
+ void EmitAutomaticVariableDecl(tree_node *decl);
+
+ /// EmitAnnotateIntrinsic - Emits call to annotate attr intrinsic
+ void EmitAnnotateIntrinsic(Value *V, tree_node *decl);
+
+ /// EmitTypeGcroot - Emits call to make type a gcroot
+ void EmitTypeGcroot(Value *V, tree_node *decl);
+
+private:
+
+ //===------------------ Render* - Convert GIMPLE to LLVM ----------------===//
- // Render* - Convert GIMPLE to LLVM.
void RenderGIMPLE_ASM(gimple stmt);
void RenderGIMPLE_ASSIGN(gimple stmt);
void RenderGIMPLE_CALL(gimple stmt);
@@ -589,56 +578,70 @@
void RenderGIMPLE_SWITCH(gimple stmt);
// Render helpers.
+
+ /// EmitAssignRHS - Convert the RHS of a scalar GIMPLE_ASSIGN to LLVM.
+ Value *EmitAssignRHS(gimple stmt);
+
+ /// EmitAssignSingleRHS - Helper for EmitAssignRHS. Handles those RHS that
+ /// are not register expressions.
+ Value *EmitAssignSingleRHS(tree_node *rhs);
+
+ /// OutputCallRHS - Convert the RHS of a GIMPLE_CALL.
+ Value *OutputCallRHS(gimple stmt, const MemRef *DestLoc);
+
+ /// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS.
void WriteScalarToLHS(tree lhs, Value *Scalar);
private:
- void EmitAutomaticVariableDecl(tree_node *decl);
- /// isNoopCast - Return true if a cast from V to Ty does not change any bits.
- ///
- static bool isNoopCast(Value *V, const Type *Ty);
+ //===------------ Emit* - Convert register expression to LLVM -----------===//
- /// EmitAnnotateIntrinsic - Emits call to annotate attr intrinsic
- void EmitAnnotateIntrinsic(Value *V, tree_node *decl);
+ /// EmitRegister - Convert the specified gimple register or local constant of
+ /// register type to an LLVM value. Only creates code in the entry block.
+ Value *EmitRegister(tree_node *reg);
- /// EmitTypeGcroot - Emits call to make type a gcroot
- void EmitTypeGcroot(Value *V, tree_node *decl);
-private:
+ /// EmitSSA_NAME - Return the defining value of the given SSA_NAME.
+ /// Only creates code in the entry block.
+ Value *EmitSSA_NAME(tree_node *reg);
- // Expressions.
- Value *EmitGimpleAssignSingleRHS(tree_node *rhs);
- Value *EmitGimpleAssignRHS(gimple stmt);
- Value *EmitGimpleCallRHS(gimple stmt, const MemRef *DestLoc);
- Value *EmitLoadOfLValue(tree_node *exp);
- Value *EmitADDR_EXPR(tree_node *exp);
- Value *EmitOBJ_TYPE_REF(tree_node *exp);
- Value *EmitCallOf(Value *Callee, gimple stmt, const MemRef *DestLoc,
- const AttrListPtr &PAL);
- Value *EmitNOP_EXPR(tree_node *type, tree_node *op);
- Value *EmitCONVERT_EXPR(tree_node *type, tree_node *op);
- Value *EmitNEGATE_EXPR(tree_node *op);
- Value *EmitCONJ_EXPR(tree_node *op);
+ // Unary expressions.
Value *EmitABS_EXPR(tree_node *op);
Value *EmitBIT_NOT_EXPR(tree_node *op);
+ Value *EmitCONJ_EXPR(tree_node *op);
+ Value *EmitCONVERT_EXPR(tree_node *type, tree_node *op);
+ Value *EmitNEGATE_EXPR(tree_node *op);
+ Value *EmitNOP_EXPR(tree_node *type, tree_node *op);
+ Value *EmitPAREN_EXPR(tree_node *exp);
Value *EmitTRUTH_NOT_EXPR(tree_node *type, tree_node *op);
+
+ // Comparisons.
Value *EmitCompare(tree_node *lhs, tree_node *rhs, tree_code code);
+
+ // Binary expressions.
Value *EmitBinOp(tree_node *type, tree_code code, tree_node *op0,
tree_node *op1, unsigned Opc);
- Value *EmitTruthOp(tree_node *type, tree_node *op0, tree_node *op1,
- unsigned Opc);
- Value *EmitShiftOp(tree_node *op0, tree_node* op1, unsigned Opc);
- Value *EmitRotateOp(tree_node *type, tree_node *op0, tree_node *op1,
- unsigned Opc1, unsigned Opc2);
Value *EmitMinMaxExpr(tree_node *type, tree_node *op0, tree_node* op1,
unsigned UIPred, unsigned SIPred, unsigned Opc,
bool isMax);
- Value *EmitFLOOR_MOD_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
+ Value *EmitRotateOp(tree_node *type, tree_node *op0, tree_node *op1,
+ unsigned Opc1, unsigned Opc2);
+ Value *EmitShiftOp(tree_node *op0, tree_node* op1, unsigned Opc);
+ Value *EmitTruthOp(tree_node *type, tree_node *op0, tree_node *op1,
+ unsigned Opc);
Value *EmitCEIL_DIV_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
+ Value *EmitCOMPLEX_EXPR(tree op0, tree op1);
Value *EmitFLOOR_DIV_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
+ Value *EmitFLOOR_MOD_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
+ Value *EmitPOINTER_PLUS_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
Value *EmitROUND_DIV_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
+
+
+ Value *EmitLoadOfLValue(tree_node *exp);
+ Value *EmitOBJ_TYPE_REF(tree_node *exp);
+ Value *EmitADDR_EXPR(tree_node *exp);
+ Value *EmitCallOf(Value *Callee, gimple stmt, const MemRef *DestLoc,
+ const AttrListPtr &PAL);
Value *EmitFieldAnnotation(Value *FieldPtr, tree_node *FieldDecl);
- Value *EmitPOINTER_PLUS_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
- Value *EmitPAREN_EXPR(tree_node *exp);
// Exception Handling.
Value *EmitEXC_PTR_EXPR(tree_node *exp);
@@ -696,7 +699,6 @@
// Complex Math Expressions.
Value *CreateComplex(Value *Real, Value *Imag);
void SplitComplex(Value *Complex, Value *&Real, Value *&Imag);
- Value *EmitCOMPLEX_EXPR(tree op0, tree op1);
Value *EmitComplexBinOp(tree_code code, tree_node *op0, tree_node *op1);
// L-Value Expressions.
@@ -717,6 +719,22 @@
Value *EmitREAL_CST(tree_node *exp);
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.
+ 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.
+ Value *EmitInvariantAddress(tree_node *addr);
+
+ /// EmitRegisterConstant - Convert the given global constant of register type
+ /// to an LLVM constant. Creates no code, only constants.
+ Constant *EmitRegisterConstant(tree_node *reg);
+
+private:
// Optional target defined builtin intrinsic expanding function.
bool TargetIntrinsicLower(gimple stmt,
tree_node *fndecl,
More information about the llvm-commits
mailing list