[llvm-commits] [gcc-plugin] r82219 - in /gcc-plugin/trunk: llvm-convert.cpp llvm-internal.h
Duncan Sands
baldrick at free.fr
Fri Sep 18 05:53:05 PDT 2009
Author: baldrick
Date: Fri Sep 18 07:53:04 2009
New Revision: 82219
URL: http://llvm.org/viewvc/llvm-project?rev=82219&view=rev
Log:
Handle GIMPLE_ASSIGN directly, rather than going via trees.
This is the most complicated conversion, since GIMPLE_ASSIGN
can have binary and unary operations encoded in it. Hopefully
I didn't break anything :)
Modified:
gcc-plugin/trunk/llvm-convert.cpp
gcc-plugin/trunk/llvm-internal.h
Modified: gcc-plugin/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/gcc-plugin/trunk/llvm-convert.cpp?rev=82219&r1=82218&r2=82219&view=diff
==============================================================================
--- gcc-plugin/trunk/llvm-convert.cpp (original)
+++ gcc-plugin/trunk/llvm-convert.cpp Fri Sep 18 07:53:04 2009
@@ -948,7 +948,6 @@
gimple gimple_stmt = gsi_stmt(gsi);
switch (gimple_code(gimple_stmt)) {
- case GIMPLE_ASSIGN:
case GIMPLE_CALL: {
// TODO Handle gimple directly, rather than converting to a tree.
tree stmt = gimple_to_tree(gimple_stmt);
@@ -971,6 +970,10 @@
RenderGIMPLE_ASM(gimple_stmt);
break;
+ case GIMPLE_ASSIGN:
+ RenderGIMPLE_ASSIGN(gimple_stmt);
+ break;
+
case GIMPLE_COND:
RenderGIMPLE_COND(gimple_stmt);
break;
@@ -1086,16 +1089,26 @@
case NON_LVALUE_EXPR: Result = Emit(TREE_OPERAND(exp, 0), DestLoc); break;
// Unary Operators
- case NOP_EXPR: Result = EmitNOP_EXPR(exp, DestLoc); break;
+ case NOP_EXPR:
+ Result = EmitNOP_EXPR(TREE_TYPE(exp), TREE_OPERAND(exp, 0), DestLoc);
+ break;
case FIX_TRUNC_EXPR:
case FLOAT_EXPR:
- case CONVERT_EXPR: Result = EmitCONVERT_EXPR(exp, DestLoc); break;
+ case CONVERT_EXPR:
+ Result = EmitCONVERT_EXPR(TREE_TYPE(exp), TREE_OPERAND(exp, 0));
+ break;
case VIEW_CONVERT_EXPR: Result = EmitVIEW_CONVERT_EXPR(exp, DestLoc); break;
- case NEGATE_EXPR: Result = EmitNEGATE_EXPR(exp, DestLoc); break;
- case CONJ_EXPR: Result = EmitCONJ_EXPR(exp, DestLoc); break;
- case ABS_EXPR: Result = EmitABS_EXPR(exp); break;
- case BIT_NOT_EXPR: Result = EmitBIT_NOT_EXPR(exp); break;
- case TRUTH_NOT_EXPR: Result = EmitTRUTH_NOT_EXPR(exp); break;
+ case NEGATE_EXPR:
+ Result = EmitNEGATE_EXPR(TREE_OPERAND(exp, 0), DestLoc);
+ break;
+ case CONJ_EXPR:
+ Result = EmitCONJ_EXPR(TREE_OPERAND(exp, 0), DestLoc);
+ break;
+ case ABS_EXPR: Result = EmitABS_EXPR(TREE_OPERAND(exp, 0)); break;
+ case BIT_NOT_EXPR: Result = EmitBIT_NOT_EXPR(TREE_OPERAND(exp, 0)); break;
+ case TRUTH_NOT_EXPR:
+ Result = EmitTRUTH_NOT_EXPR(TREE_TYPE(exp), TREE_OPERAND(exp, 0));
+ break;
// Binary Operators
case LT_EXPR:
@@ -1118,72 +1131,139 @@
Result = Builder.CreateZExt(Result, ConvertType(TREE_TYPE(exp)));
break;
case PLUS_EXPR:
- Result = EmitBinOp(exp, DestLoc,
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
FLOAT_TYPE_P(TREE_TYPE(exp)) ?
Instruction::FAdd :
Instruction::Add);
break;
case MINUS_EXPR:
- Result = EmitBinOp(exp, DestLoc,
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
FLOAT_TYPE_P(TREE_TYPE(exp)) ?
Instruction::FSub :
Instruction::Sub);
break;
case MULT_EXPR:
- Result = EmitBinOp(exp, DestLoc,
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
FLOAT_TYPE_P(TREE_TYPE(exp)) ?
Instruction::FMul :
Instruction::Mul);
break;
- case EXACT_DIV_EXPR: Result = EmitEXACT_DIV_EXPR(exp, DestLoc); break;
+ case EXACT_DIV_EXPR:
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
+ TYPE_UNSIGNED(TREE_TYPE(exp)) ?
+ Instruction::UDiv : Instruction::SDiv);
case TRUNC_DIV_EXPR:
if (TYPE_UNSIGNED(TREE_TYPE(exp)))
- Result = EmitBinOp(exp, DestLoc, Instruction::UDiv);
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
+ Instruction::UDiv);
else
- Result = EmitBinOp(exp, DestLoc, Instruction::SDiv);
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
+ Instruction::SDiv);
+ break;
+ case RDIV_EXPR: Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1),
+ DestLoc, Instruction::FDiv); break;
+ case CEIL_DIV_EXPR:
+ Result = EmitCEIL_DIV_EXPR(TREE_TYPE(exp), TREE_OPERAND(exp, 0),
+ TREE_OPERAND(exp, 1));
+ break;
+ case FLOOR_DIV_EXPR:
+ Result = EmitFLOOR_DIV_EXPR(TREE_TYPE(exp), TREE_OPERAND(exp, 0),
+ TREE_OPERAND(exp, 1));
+ break;
+ case ROUND_DIV_EXPR:
+ Result = EmitROUND_DIV_EXPR(TREE_TYPE(exp), TREE_OPERAND(exp, 0),
+ TREE_OPERAND(exp, 1));
break;
- case RDIV_EXPR: Result = EmitBinOp(exp, DestLoc, Instruction::FDiv); break;
- case CEIL_DIV_EXPR: Result = EmitCEIL_DIV_EXPR(exp); break;
- case FLOOR_DIV_EXPR: Result = EmitFLOOR_DIV_EXPR(exp); break;
- case ROUND_DIV_EXPR: Result = EmitROUND_DIV_EXPR(exp); break;
case TRUNC_MOD_EXPR:
if (TYPE_UNSIGNED(TREE_TYPE(exp)))
- Result = EmitBinOp(exp, DestLoc, Instruction::URem);
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
+ Instruction::URem);
else
- Result = EmitBinOp(exp, DestLoc, Instruction::SRem);
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
+ Instruction::SRem);
+ break;
+ case FLOOR_MOD_EXPR:
+ Result = EmitFLOOR_MOD_EXPR(TREE_TYPE(exp), TREE_OPERAND(exp, 0),
+ TREE_OPERAND(exp, 1));
+ break;
+ case BIT_AND_EXPR:
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
+ Instruction::And);
+ break;
+ case BIT_IOR_EXPR:
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
+ Instruction::Or);
+ break;
+ case BIT_XOR_EXPR:
+ Result = EmitBinOp(TREE_TYPE(exp), TREE_CODE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc,
+ Instruction::Xor);
+ break;
+ case TRUTH_AND_EXPR:
+ Result = EmitTruthOp(TREE_TYPE(exp), TREE_OPERAND(exp, 0),
+ TREE_OPERAND(exp, 1), Instruction::And);
+ break;
+ case TRUTH_OR_EXPR:
+ Result = EmitTruthOp(TREE_TYPE(exp), TREE_OPERAND(exp, 0),
+ TREE_OPERAND(exp, 1), Instruction::Or);
+ break;
+ case TRUTH_XOR_EXPR:
+ Result = EmitTruthOp(TREE_TYPE(exp), TREE_OPERAND(exp, 0),
+ TREE_OPERAND(exp, 1), Instruction::Xor);
break;
- case FLOOR_MOD_EXPR: Result = EmitFLOOR_MOD_EXPR(exp, DestLoc); break;
- case BIT_AND_EXPR: Result = EmitBinOp(exp, DestLoc, Instruction::And);break;
- case BIT_IOR_EXPR: Result = EmitBinOp(exp, DestLoc, Instruction::Or );break;
- case BIT_XOR_EXPR: Result = EmitBinOp(exp, DestLoc, Instruction::Xor);break;
- case TRUTH_AND_EXPR: Result = EmitTruthOp(exp, Instruction::And); break;
- case TRUTH_OR_EXPR: Result = EmitTruthOp(exp, Instruction::Or); break;
- case TRUTH_XOR_EXPR: Result = EmitTruthOp(exp, Instruction::Xor); break;
case RSHIFT_EXPR:
- Result = EmitShiftOp(exp,DestLoc,
- TYPE_UNSIGNED(TREE_TYPE(exp)) ? Instruction::LShr : Instruction::AShr);
+ Result = EmitShiftOp(TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1),
+ TYPE_UNSIGNED(TREE_TYPE(exp)) ?
+ Instruction::LShr : Instruction::AShr);
+ break;
+ case LSHIFT_EXPR:
+ Result = EmitShiftOp(TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1),
+ Instruction::Shl);
break;
- case LSHIFT_EXPR: Result = EmitShiftOp(exp,DestLoc,Instruction::Shl);break;
case RROTATE_EXPR:
- Result = EmitRotateOp(exp, Instruction::LShr, Instruction::Shl);
+ Result = EmitRotateOp(TREE_TYPE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1),
+ Instruction::LShr, Instruction::Shl);
break;
case LROTATE_EXPR:
- Result = EmitRotateOp(exp, Instruction::Shl, Instruction::LShr);
+ Result = EmitRotateOp(TREE_TYPE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1),
+ Instruction::Shl, Instruction::LShr);
break;
case MIN_EXPR:
- Result = EmitMinMaxExpr(exp, ICmpInst::ICMP_ULE, ICmpInst::ICMP_SLE,
- FCmpInst::FCMP_OLE);
+ Result = EmitMinMaxExpr(TREE_TYPE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1),
+ ICmpInst::ICMP_ULE, ICmpInst::ICMP_SLE,
+ FCmpInst::FCMP_OLE, false);
break;
case MAX_EXPR:
- Result = EmitMinMaxExpr(exp, ICmpInst::ICMP_UGE, ICmpInst::ICMP_SGE,
- FCmpInst::FCMP_OGE);
+ Result = EmitMinMaxExpr(TREE_TYPE(exp),
+ TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1),
+ ICmpInst::ICMP_UGE, ICmpInst::ICMP_SGE,
+ FCmpInst::FCMP_OGE, true);
break;
case CONSTRUCTOR: Result = EmitCONSTRUCTOR(exp, DestLoc); break;
- case POINTER_PLUS_EXPR: Result = EmitPOINTER_PLUS_EXPR(exp); break;
+ case POINTER_PLUS_EXPR:
+ Result = EmitPOINTER_PLUS_EXPR(TREE_TYPE(exp), TREE_OPERAND(exp, 0),
+ TREE_OPERAND(exp, 1));
+ break;
// Complex Math Expressions.
case COMPLEX_CST: EmitCOMPLEX_CST (exp, DestLoc); break;
- case COMPLEX_EXPR: EmitCOMPLEX_EXPR(exp, DestLoc); break;
+ case COMPLEX_EXPR:
+ EmitCOMPLEX_EXPR(TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1), DestLoc);
+ break;
// Constant Expressions
case INTEGER_CST:
@@ -2276,6 +2356,122 @@
return SSANames[exp] = LI;
}
+Value *TreeToLLVM::EmitGimpleAssignRHS(gimple stmt, const MemRef *DestLoc) {
+ if (get_gimple_rhs_class(gimple_expr_code(stmt)) == GIMPLE_SINGLE_RHS)
+ return Emit(gimple_assign_rhs1 (stmt), DestLoc);
+
+ 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, DestLoc);
+ case CONVERT_EXPR:
+ case FIX_TRUNC_EXPR:
+ case FLOAT_EXPR:
+ return EmitCONVERT_EXPR(type, rhs1);
+ case NEGATE_EXPR:
+ return EmitNEGATE_EXPR(rhs1, DestLoc);
+ case NON_LVALUE_EXPR:
+ return Emit(rhs1, DestLoc);
+ case NOP_EXPR:
+ return EmitNOP_EXPR(type, rhs1, DestLoc);
+ 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, DestLoc, Instruction::And);
+ case BIT_IOR_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, DestLoc, Instruction::Or);
+ case BIT_XOR_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, DestLoc, Instruction::Xor);
+ case CEIL_DIV_EXPR:
+ return EmitCEIL_DIV_EXPR(type, rhs1, rhs2);
+ case COMPLEX_EXPR:
+ EmitCOMPLEX_EXPR(rhs1, rhs2, DestLoc);
+ return 0;
+ case EXACT_DIV_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, DestLoc, 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, DestLoc, FLOAT_TYPE_P(type) ?
+ Instruction::FSub : Instruction::Sub);
+ case MULT_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, DestLoc, FLOAT_TYPE_P(type) ?
+ Instruction::FMul : Instruction::Mul);
+ case PLUS_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, DestLoc, 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, DestLoc, 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, DestLoc, TYPE_UNSIGNED(type) ?
+ Instruction::UDiv : Instruction::SDiv);
+ case TRUNC_MOD_EXPR:
+ return EmitBinOp(type, code, rhs1, rhs2, DestLoc, 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);
+ }
+}
+
/// 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.
@@ -3024,32 +3220,26 @@
return RHS;
}
-Value *TreeToLLVM::EmitNOP_EXPR(tree exp, const MemRef *DestLoc) {
- if (TREE_CODE(TREE_TYPE(exp)) == VOID_TYPE && // deleted statement.
- TREE_CODE(TREE_OPERAND(exp, 0)) == INTEGER_CST)
- return 0;
- tree Op = TREE_OPERAND(exp, 0);
- const Type *Ty = ConvertType(TREE_TYPE(exp));
- bool OpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(Op));
- bool ExpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
+Value *TreeToLLVM::EmitNOP_EXPR(tree type, tree op, const MemRef *DestLoc) {
+ const Type *Ty = ConvertType(type);
+ bool OpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op));
+ bool ExpIsSigned = !TYPE_UNSIGNED(type);
if (DestLoc == 0) {
// Scalar to scalar copy.
- assert(!isAggregateTreeType(TREE_TYPE(Op))
+ assert(!isAggregateTreeType(TREE_TYPE(op))
&& "Aggregate to scalar nop_expr!");
- Value *OpVal = Emit(Op, DestLoc);
- if (Ty == Type::getVoidTy(Context)) return 0;
- return CastToAnyType(OpVal, OpIsSigned, Ty, ExpIsSigned);
- } else if (isAggregateTreeType(TREE_TYPE(Op))) {
+ return CastToAnyType(Emit(op, 0), OpIsSigned, Ty, ExpIsSigned);
+ } else if (isAggregateTreeType(TREE_TYPE(op))) {
// Aggregate to aggregate copy.
MemRef NewLoc = *DestLoc;
NewLoc.Ptr = BitCastToType(DestLoc->Ptr, PointerType::getUnqual(Ty));
- Value *OpVal = Emit(Op, &NewLoc);
+ Value *OpVal = Emit(op, &NewLoc);
assert(OpVal == 0 && "Shouldn't cast scalar to aggregate!");
return 0;
}
// Scalar to aggregate copy.
- Value *OpVal = Emit(Op, 0);
+ Value *OpVal = Emit(op, 0);
Value *Ptr = BitCastToType(DestLoc->Ptr,
PointerType::getUnqual(OpVal->getType()));
StoreInst *St = Builder.CreateStore(OpVal, Ptr, DestLoc->Volatile);
@@ -3057,12 +3247,10 @@
return 0;
}
-Value *TreeToLLVM::EmitCONVERT_EXPR(tree exp, const MemRef *DestLoc) {
- assert(!DestLoc && "Cannot handle aggregate casts!");
- Value *Op = Emit(TREE_OPERAND(exp, 0), 0);
- bool OpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
- bool ExpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
- return CastToAnyType(Op, OpIsSigned, ConvertType(TREE_TYPE(exp)),ExpIsSigned);
+Value *TreeToLLVM::EmitCONVERT_EXPR(tree type, tree op) {
+ bool OpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op));
+ bool ExpIsSigned = !TYPE_UNSIGNED(type);
+ return CastToAnyType(Emit(op, 0), OpIsSigned, ConvertType(type), ExpIsSigned);
}
Value *TreeToLLVM::EmitVIEW_CONVERT_EXPR(tree exp, const MemRef *DestLoc) {
@@ -3156,26 +3344,19 @@
return Builder.CreateBitCast(OpVal, DestTy);
}
-Value *TreeToLLVM::EmitNEGATE_EXPR(tree exp, const MemRef *DestLoc) {
+Value *TreeToLLVM::EmitNEGATE_EXPR(tree op, const MemRef *DestLoc) {
if (!DestLoc) {
- Value *V = Emit(TREE_OPERAND(exp, 0), 0);
+ Value *V = Emit(op, 0);
if (V->getType()->isFPOrFPVector())
return Builder.CreateFNeg(V);
- if (!isa<PointerType>(V->getType()))
- return Builder.CreateNeg(V);
-
- // GCC allows NEGATE_EXPR on pointers as well. Cast to int, negate, cast
- // back.
- V = CastToAnyType(V, false, TD.getIntPtrType(Context), false);
- V = Builder.CreateNeg(V);
- return CastToType(Instruction::IntToPtr, V, ConvertType(TREE_TYPE(exp)));
+ return Builder.CreateNeg(V);
}
// Emit the operand to a temporary.
const Type *ComplexTy =
cast<PointerType>(DestLoc->Ptr->getType())->getElementType();
MemRef Tmp = CreateTempLoc(ComplexTy);
- Emit(TREE_OPERAND(exp, 0), &Tmp);
+ Emit(op, &Tmp);
// Handle complex numbers: -(a+ib) = -a + i*-b
Value *R, *I;
@@ -3191,13 +3372,13 @@
return 0;
}
-Value *TreeToLLVM::EmitCONJ_EXPR(tree exp, const MemRef *DestLoc) {
+Value *TreeToLLVM::EmitCONJ_EXPR(tree op, const MemRef *DestLoc) {
assert(DestLoc && "CONJ_EXPR only applies to complex numbers.");
// Emit the operand to a temporary.
const Type *ComplexTy =
cast<PointerType>(DestLoc->Ptr->getType())->getElementType();
MemRef Tmp = CreateTempLoc(ComplexTy);
- Emit(TREE_OPERAND(exp, 0), &Tmp);
+ Emit(op, &Tmp);
// Handle complex numbers: ~(a+ib) = a + i*-b
Value *R, *I;
@@ -3210,11 +3391,11 @@
return 0;
}
-Value *TreeToLLVM::EmitABS_EXPR(tree exp) {
- Value *Op = Emit(TREE_OPERAND(exp, 0), 0);
+Value *TreeToLLVM::EmitABS_EXPR(tree op) {
+ Value *Op = Emit(op, 0);
if (!Op->getType()->isFloatingPoint()) {
Value *OpN = Builder.CreateNeg(Op, (Op->getNameStr()+"neg").c_str());
- ICmpInst::Predicate pred = TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0))) ?
+ ICmpInst::Predicate pred = TYPE_UNSIGNED(TREE_TYPE(op)) ?
ICmpInst::ICMP_UGE : ICmpInst::ICMP_SGE;
Value *Cmp = Builder.CreateICmp(pred, Op,
Constant::getNullValue(Op->getType()), "abscond");
@@ -3254,30 +3435,18 @@
return IntegerType::get(Context, Ty->getPrimitiveSizeInBits());
}
-Value *TreeToLLVM::EmitBIT_NOT_EXPR(tree exp) {
- Value *Op = Emit(TREE_OPERAND(exp, 0), 0);
- const Type *Ty = Op->getType();
- if (isa<PointerType>(Ty)) {
- assert (TREE_CODE(TREE_TYPE(exp)) == INTEGER_TYPE &&
- "Expected integer type here");
- Ty = ConvertType(TREE_TYPE(exp));
- Op = CastToType(Instruction::PtrToInt, Op, Ty);
- } else if (Ty->isFloatingPoint() ||
- (isa<VectorType>(Ty) &&
- cast<VectorType>(Ty)->getElementType()->isFloatingPoint())) {
- Op = BitCastToType(Op, getSuitableBitCastIntType(Ty));
- }
- return BitCastToType(Builder.CreateNot(Op,
- (Op->getNameStr()+"not").c_str()),Ty);
+Value *TreeToLLVM::EmitBIT_NOT_EXPR(tree op) {
+ Value *Op = Emit(op, 0);
+ return Builder.CreateNot(Op, (Op->getNameStr()+"not").c_str());
}
-Value *TreeToLLVM::EmitTRUTH_NOT_EXPR(tree exp) {
- Value *V = Emit(TREE_OPERAND(exp, 0), 0);
+Value *TreeToLLVM::EmitTRUTH_NOT_EXPR(tree type, tree op) {
+ Value *V = Emit(op, 0);
if (V->getType() != Type::getInt1Ty(Context))
V = Builder.CreateICmpNE(V,
Constant::getNullValue(V->getType()), "toBool");
V = Builder.CreateNot(V, (V->getNameStr()+"not").c_str());
- return CastToUIntType(V, ConvertType(TREE_TYPE(exp)));
+ return CastToUIntType(V, ConvertType(type));
}
/// EmitCompare - Compare LHS with RHS using the appropriate comparison code.
@@ -3381,24 +3550,25 @@
/// EmitBinOp - 'exp' is a binary operator.
///
-Value *TreeToLLVM::EmitBinOp(tree exp, const MemRef *DestLoc, unsigned Opc) {
- const Type *Ty = ConvertType(TREE_TYPE(exp));
+Value *TreeToLLVM::EmitBinOp(tree type, tree_code code, tree op0, tree op1,
+ const MemRef *DestLoc, unsigned Opc) {
+ const Type *Ty = ConvertType(type);
if (isa<StructType>(Ty))
- return EmitComplexBinOp(exp, DestLoc);
+ return EmitComplexBinOp(type, code, op0, op1, DestLoc);
assert(Ty->isSingleValueType() && DestLoc == 0 &&
"Bad binary operation!");
- Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
- Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
+ Value *LHS = Emit(op0, 0);
+ Value *RHS = Emit(op1, 0);
// GCC has no problem with things like "xor uint X, int 17", and X-Y, where
// X and Y are pointer types, but the result is an integer. As such, convert
// everything to the result type.
- bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
- bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 1)));
- bool TyIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
- bool IsExactDiv = TREE_CODE(exp) == EXACT_DIV_EXPR;
- bool IsPlus = TREE_CODE(exp) == PLUS_EXPR;
+ bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op0));
+ bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op1));
+ bool TyIsSigned = !TYPE_UNSIGNED(type);
+ bool IsExactDiv = code == EXACT_DIV_EXPR;
+ bool IsPlus = code == PLUS_EXPR;
LHS = CastToAnyType(LHS, LHSIsSigned, Ty, TyIsSigned);
RHS = CastToAnyType(RHS, RHSIsSigned, Ty, TyIsSigned);
@@ -3429,9 +3599,9 @@
return V;
}
-Value *TreeToLLVM::EmitTruthOp(tree exp, unsigned Opc) {
- Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
- Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
+Value *TreeToLLVM::EmitTruthOp(tree type, tree op0, tree op1, unsigned Opc) {
+ Value *LHS = Emit(op0, 0);
+ Value *RHS = Emit(op1, 0);
// This is a truth operation like the strict &&,||,^^. Convert to bool as
// a test against zero
@@ -3443,17 +3613,13 @@
"toBool");
Value *Res = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS);
- return CastToType(Instruction::ZExt, Res, ConvertType(TREE_TYPE(exp)));
+ return CastToType(Instruction::ZExt, Res, ConvertType(type));
}
-Value *TreeToLLVM::EmitShiftOp(tree exp, const MemRef *DestLoc, unsigned Opc) {
- assert(DestLoc == 0 && "aggregate shift?");
- const Type *Ty = ConvertType(TREE_TYPE(exp));
- assert(!isa<PointerType>(Ty) && "Pointer arithmetic!?");
-
- Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
- Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
+Value *TreeToLLVM::EmitShiftOp(tree op0, tree op1, unsigned Opc) {
+ Value *LHS = Emit(op0, 0);
+ Value *RHS = Emit(op1, 0);
if (RHS->getType() != LHS->getType())
RHS = Builder.CreateIntCast(RHS, LHS->getType(), false,
(RHS->getNameStr()+".cast").c_str());
@@ -3461,17 +3627,10 @@
return Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS);
}
-Value *TreeToLLVM::EmitRotateOp(tree exp, unsigned Opc1, unsigned Opc2) {
- Value *In = Emit(TREE_OPERAND(exp, 0), 0);
- Value *Amt = Emit(TREE_OPERAND(exp, 1), 0);
-
- if (isa<PointerType>(In->getType())) {
- const Type *Ty =
- IntegerType::get(Context,
- TYPE_PRECISION(TREE_TYPE (TREE_OPERAND (exp, 0))));
- In = Builder.CreatePtrToInt(In, Ty,
- (In->getNameStr()+".cast").c_str());
- }
+Value *TreeToLLVM::EmitRotateOp(tree type, tree op0, tree op1,
+ unsigned Opc1, unsigned Opc2) {
+ Value *In = Emit(op0, 0);
+ Value *Amt = Emit(op1, 0);
if (Amt->getType() != In->getType())
Amt = Builder.CreateIntCast(Amt, In->getType(), false,
@@ -3488,22 +3647,23 @@
// Or the two together to return them.
Value *Merge = Builder.CreateOr(V1, V2);
- return CastToUIntType(Merge, ConvertType(TREE_TYPE(exp)));
+ return CastToUIntType(Merge, ConvertType(type));
}
-Value *TreeToLLVM::EmitMinMaxExpr(tree exp, unsigned UIPred, unsigned SIPred,
- unsigned FPPred) {
- Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
- Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
+Value *TreeToLLVM::EmitMinMaxExpr(tree type, tree op0, tree op1,
+ unsigned UIPred, unsigned SIPred,
+ unsigned FPPred, bool isMax) {
+ Value *LHS = Emit(op0, 0);
+ Value *RHS = Emit(op1, 0);
- const Type *Ty = ConvertType(TREE_TYPE(exp));
+ const Type *Ty = ConvertType(type);
// The LHS, RHS and Ty could be integer, floating or pointer typed. We need
// to convert the LHS and RHS into the destination type before doing the
// comparison. Use CastInst::getCastOpcode to get this right.
- bool TyIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
- bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
- bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 1)));
+ bool TyIsSigned = !TYPE_UNSIGNED(type);
+ bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op0));
+ bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op1));
Instruction::CastOps opcode =
CastInst::getCastOpcode(LHS, LHSIsSigned, Ty, TyIsSigned);
LHS = CastToType(opcode, LHS, Ty);
@@ -3513,40 +3673,30 @@
Value *Compare;
if (LHS->getType()->isFloatingPoint())
Compare = Builder.CreateFCmp(FCmpInst::Predicate(FPPred), LHS, RHS);
- else if (TYPE_UNSIGNED(TREE_TYPE(exp)))
+ else if (TYPE_UNSIGNED(type))
Compare = Builder.CreateICmp(ICmpInst::Predicate(UIPred), LHS, RHS);
else
Compare = Builder.CreateICmp(ICmpInst::Predicate(SIPred), LHS, RHS);
- return Builder.CreateSelect(Compare, LHS, RHS,
- TREE_CODE(exp) == MAX_EXPR ? "max" : "min");
+ return Builder.CreateSelect(Compare, LHS, RHS, isMax ? "max" : "min");
}
-Value *TreeToLLVM::EmitEXACT_DIV_EXPR(tree exp, const MemRef *DestLoc) {
- // Unsigned EXACT_DIV_EXPR -> normal udiv.
- if (TYPE_UNSIGNED(TREE_TYPE(exp)))
- return EmitBinOp(exp, DestLoc, Instruction::UDiv);
-
- // Otherwise, emit this as a normal signed divide.
- return EmitBinOp(exp, DestLoc, Instruction::SDiv);
-}
-
-Value *TreeToLLVM::EmitFLOOR_MOD_EXPR(tree exp, const MemRef *DestLoc) {
+Value *TreeToLLVM::EmitFLOOR_MOD_EXPR(tree type, tree op0, tree op1) {
// Notation: FLOOR_MOD_EXPR <-> Mod, TRUNC_MOD_EXPR <-> Rem.
// We express Mod in terms of Rem as follows: if RHS exactly divides LHS,
// or the values of LHS and RHS have the same sign, then Mod equals Rem.
// Otherwise Mod equals Rem + RHS. This means that LHS Mod RHS traps iff
// LHS Rem RHS traps.
- if (TYPE_UNSIGNED(TREE_TYPE(exp)))
+ if (TYPE_UNSIGNED(type))
// LHS and RHS values must have the same sign if their type is unsigned.
- return EmitBinOp(exp, DestLoc, Instruction::URem);
+ return EmitBinOp(type, FLOOR_MOD_EXPR, op0, op1, 0, Instruction::URem);
- const Type *Ty = ConvertType(TREE_TYPE(exp));
+ const Type *Ty = ConvertType(type);
Constant *Zero = ConstantInt::get(Ty, 0);
- Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
- Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
+ Value *LHS = Emit(op0, 0);
+ Value *RHS = Emit(op1, 0);
// The two possible values for Mod.
Value *Rem = Builder.CreateSRem(LHS, RHS, "rem");
@@ -3564,7 +3714,7 @@
return Builder.CreateSelect(SameAsRem, Rem, RemPlusRHS, "mod");
}
-Value *TreeToLLVM::EmitCEIL_DIV_EXPR(tree exp) {
+Value *TreeToLLVM::EmitCEIL_DIV_EXPR(tree type, tree op0, tree op1) {
// Notation: CEIL_DIV_EXPR <-> CDiv, TRUNC_DIV_EXPR <-> Div.
// CDiv calculates LHS/RHS by rounding up to the nearest integer. In terms
@@ -3573,15 +3723,15 @@
// LHS CDiv RHS = (LHS - Sign(RHS)) Div RHS + 1
// otherwise.
- const Type *Ty = ConvertType(TREE_TYPE(exp));
+ const Type *Ty = ConvertType(type);
Constant *Zero = ConstantInt::get(Ty, 0);
Constant *One = ConstantInt::get(Ty, 1);
Constant *MinusOne = Constant::getAllOnesValue(Ty);
- Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
- Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
+ Value *LHS = Emit(op0, 0);
+ Value *RHS = Emit(op1, 0);
- if (!TYPE_UNSIGNED(TREE_TYPE(exp))) {
+ if (!TYPE_UNSIGNED(type)) {
// In the case of signed arithmetic, we calculate CDiv as follows:
// LHS CDiv RHS = (LHS - Sign(RHS) * Offset) Div RHS + Offset,
// where Offset is 1 if LHS and RHS have the same sign and LHS is
@@ -3629,10 +3779,10 @@
return Builder.CreateAdd(CDiv, Offset, "cdiv");
}
-Value *TreeToLLVM::EmitFLOOR_DIV_EXPR(tree exp) {
+Value *TreeToLLVM::EmitFLOOR_DIV_EXPR(tree type, tree op0, tree op1) {
// Notation: FLOOR_DIV_EXPR <-> FDiv, TRUNC_DIV_EXPR <-> Div.
- Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
- Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
+ Value *LHS = Emit(op0, 0);
+ Value *RHS = Emit(op1, 0);
// FDiv calculates LHS/RHS by rounding down to the nearest integer. In terms
// of Div this means if the values of LHS and RHS have the same sign or if LHS
@@ -3640,12 +3790,12 @@
// LHS FDiv RHS = (LHS + Sign(RHS)) Div RHS - 1
// otherwise.
- if (TYPE_UNSIGNED(TREE_TYPE(exp)))
+ if (TYPE_UNSIGNED(type))
// In the case of unsigned arithmetic, LHS and RHS necessarily have the
// same sign, so FDiv is the same as Div.
return Builder.CreateUDiv(LHS, RHS, "fdiv");
- const Type *Ty = ConvertType(TREE_TYPE(exp));
+ const Type *Ty = ConvertType(type);
Constant *Zero = ConstantInt::get(Ty, 0);
Constant *One = ConstantInt::get(Ty, 1);
Constant *MinusOne = Constant::getAllOnesValue(Ty);
@@ -3678,7 +3828,7 @@
return Builder.CreateSub(FDiv, Offset, "fdiv");
}
-Value *TreeToLLVM::EmitROUND_DIV_EXPR(tree exp) {
+Value *TreeToLLVM::EmitROUND_DIV_EXPR(tree type, tree op0, tree op1) {
// Notation: ROUND_DIV_EXPR <-> RDiv, TRUNC_DIV_EXPR <-> Div.
// RDiv calculates LHS/RHS by rounding to the nearest integer. Ties
@@ -3691,14 +3841,14 @@
// required to ensure correct results. The details depend on whether
// we are doing signed or unsigned arithmetic.
- const Type *Ty = ConvertType(TREE_TYPE(exp));
+ const Type *Ty = ConvertType(type);
Constant *Zero = ConstantInt::get(Ty, 0);
Constant *Two = ConstantInt::get(Ty, 2);
- Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
- Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
+ Value *LHS = Emit(op0, 0);
+ Value *RHS = Emit(op1, 0);
- if (!TYPE_UNSIGNED(TREE_TYPE(exp))) {
+ if (!TYPE_UNSIGNED(type)) {
// In the case of signed arithmetic, we calculate RDiv as follows:
// LHS RDiv RHS = (sign) ( (|LHS| + (|RHS| UDiv 2)) UDiv |RHS| ),
// where sign is +1 if LHS and RHS have the same sign, -1 if their
@@ -3761,9 +3911,9 @@
return Builder.CreateAdd(Quotient, CastToUIntType(Overflowed, Ty), "rdiv");
}
-Value *TreeToLLVM::EmitPOINTER_PLUS_EXPR(tree exp) {
- Value *Ptr = Emit(TREE_OPERAND(exp, 0), 0); // The pointer.
- Value *Idx = Emit(TREE_OPERAND(exp, 1), 0); // The offset in bytes.
+Value *TreeToLLVM::EmitPOINTER_PLUS_EXPR(tree type, tree op0, tree op1) {
+ Value *Ptr = Emit(op0, 0); // The pointer.
+ Value *Idx = Emit(op1, 0); // The offset in bytes.
// Convert the pointer into an i8* and add the offset to it.
Ptr = Builder.CreateBitCast(Ptr, Type::getInt8Ty(Context)->getPointerTo());
@@ -3771,7 +3921,7 @@
Builder.CreateInBoundsGEP(Ptr, Idx) : Builder.CreateGEP(Ptr, Idx);
// The result may be of a different pointer type.
- return Builder.CreateBitCast(GEP, ConvertType(TREE_TYPE(exp)));
+ return Builder.CreateBitCast(GEP, ConvertType(type));
}
//===----------------------------------------------------------------------===//
@@ -5798,9 +5948,9 @@
}
-void TreeToLLVM::EmitCOMPLEX_EXPR(tree exp, const MemRef *DestLoc) {
- Value *Real = Emit(TREE_OPERAND(exp, 0), 0);
- Value *Imag = Emit(TREE_OPERAND(exp, 1), 0);
+void TreeToLLVM::EmitCOMPLEX_EXPR(tree op0, tree op1, const MemRef *DestLoc) {
+ Value *Real = Emit(op0, 0);
+ Value *Imag = Emit(op1, 0);
EmitStoreToComplex(*DestLoc, Real, Imag);
}
@@ -5812,13 +5962,14 @@
// EmitComplexBinOp - Note that this operates on binops like ==/!=, which return
// a bool, not a complex value.
-Value *TreeToLLVM::EmitComplexBinOp(tree exp, const MemRef *DestLoc) {
- const Type *ComplexTy = ConvertType(TREE_TYPE(TREE_OPERAND(exp, 0)));
+Value *TreeToLLVM::EmitComplexBinOp(tree type, tree_code code,
+ tree op0, tree op1, const MemRef *DestLoc) {
+ const Type *ComplexTy = ConvertType(TREE_TYPE(op0));
MemRef LHSTmp = CreateTempLoc(ComplexTy);
MemRef RHSTmp = CreateTempLoc(ComplexTy);
- Emit(TREE_OPERAND(exp, 0), &LHSTmp);
- Emit(TREE_OPERAND(exp, 1), &RHSTmp);
+ Emit(op0, &LHSTmp);
+ Emit(op1, &RHSTmp);
Value *LHSr, *LHSi;
EmitLoadFromComplex(LHSr, LHSi, LHSTmp);
@@ -5826,8 +5977,8 @@
EmitLoadFromComplex(RHSr, RHSi, RHSTmp);
Value *DSTr, *DSTi;
- switch (TREE_CODE(exp)) {
- default: TODO(exp);
+ switch (code) {
+ default: llvm_unreachable("Unhandled complex binop!");
case PLUS_EXPR: // (a+ib) + (c+id) = (a+c) + i(b+d)
if (LHSr->getType()->isFloatingPoint()) {
DSTr = Builder.CreateFAdd(LHSr, RHSr, "tmpr");
@@ -8060,6 +8211,134 @@
Builder.CreateCondBr(Cond, IfTrue, IfFalse);
}
+void TreeToLLVM::RenderGIMPLE_ASSIGN(gimple stmt) {
+ tree lhs = gimple_assign_lhs(stmt);
+
+ Value *RHS = 0;
+
+ if (!isAggregateTreeType(TREE_TYPE(lhs)))
+ RHS = Builder.CreateBitCast(EmitGimpleAssignRHS(stmt, 0),
+ 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) {
+ assert(SSANames.find(lhs) == SSANames.end() &&"Multiply defined SSA name!");
+ assert(RHS && "SSA name has aggregate type!");
+ SSANames[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.
+ assert(RHS && "Register has aggregate type!");
+ EmitModifyOfRegisterVariable(lhs, RHS);
+ return;
+ }
+
+ LValue LV = EmitLV(lhs);
+ bool isVolatile = TREE_THIS_VOLATILE(lhs);
+ unsigned Alignment = LV.getAlignment();
+ if (TREE_CODE(lhs) == COMPONENT_REF)
+ if (const StructType *STy =
+ dyn_cast<StructType>(ConvertType(TREE_TYPE(TREE_OPERAND(lhs, 0)))))
+ if (STy->isPacked())
+ // Packed struct members use 1 byte alignment
+ Alignment = 1;
+
+ if (!LV.isBitfield()) {
+ if (RHS) {
+ // Non-bitfield, scalar value. Just emit a store.
+ StoreInst *SI = Builder.CreateStore(RHS, LV.Ptr, isVolatile);
+ SI->setAlignment(Alignment);
+ return;
+ }
+
+ // Non-bitfield aggregate value.
+ MemRef NewLoc(LV.Ptr, Alignment, isVolatile);
+ // TODO: This case can presumably only happen with special gimple
+ // assign right-hand-sides. Try to simplify by exploiting this.
+ EmitGimpleAssignRHS(stmt, &NewLoc);
+ return;
+ }
+
+ // Last case, this is a store to a bitfield, so we have to emit a
+ // read/modify/write sequence.
+ assert(RHS && "Bitfield has aggregate type!");
+
+ 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);
+ }
+ }
+}
+
void TreeToLLVM::RenderGIMPLE_GOTO(gimple stmt) {
tree dest = gimple_goto_dest(stmt);
Modified: gcc-plugin/trunk/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/gcc-plugin/trunk/llvm-internal.h?rev=82219&r1=82218&r2=82219&view=diff
==============================================================================
--- gcc-plugin/trunk/llvm-internal.h (original)
+++ gcc-plugin/trunk/llvm-internal.h Fri Sep 18 07:53:04 2009
@@ -520,6 +520,7 @@
// Render* - Convert GIMPLE to LLVM.
void RenderGIMPLE_ASM(gimple_statement_d *);
+ void RenderGIMPLE_ASSIGN(gimple_statement_d *);
void RenderGIMPLE_COND(gimple_statement_d *);
void RenderGIMPLE_GOTO(gimple_statement_d *);
void RenderGIMPLE_RESX(gimple_statement_d *);
@@ -547,6 +548,7 @@
// Expressions.
Value *EmitSSA_NAME(tree_node *exp);
+ Value *EmitGimpleAssignRHS(gimple stmt, const MemRef *DestLoc);
Value *EmitLoadOfLValue(tree_node *exp, const MemRef *DestLoc);
Value *EmitOBJ_TYPE_REF(tree_node *exp, const MemRef *DestLoc);
Value *EmitADDR_EXPR(tree_node *exp);
@@ -555,28 +557,31 @@
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 *EmitNOP_EXPR(tree_node *type, tree_node *op, const MemRef *DestLoc);
+ Value *EmitCONVERT_EXPR(tree_node *type, tree_node *op);
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 *EmitNEGATE_EXPR(tree_node *op, const MemRef *DestLoc);
+ Value *EmitCONJ_EXPR(tree_node *op, const MemRef *DestLoc);
+ Value *EmitABS_EXPR(tree_node *op);
+ Value *EmitBIT_NOT_EXPR(tree_node *op);
+ Value *EmitTRUTH_NOT_EXPR(tree_node *type, tree_node *op);
Value *EmitCompare(tree_node *lhs, tree_node *rhs, tree_code code);
- Value *EmitBinOp(tree_node *exp, const MemRef *DestLoc, 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 *EmitBinOp(tree_node *type, tree_code code, tree_node *op0,
+ tree_node *op1, const MemRef *DestLoc, 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 *EmitCEIL_DIV_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
+ Value *EmitFLOOR_DIV_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
+ Value *EmitROUND_DIV_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
Value *EmitFieldAnnotation(Value *FieldPtr, tree_node *FieldDecl);
- Value *EmitPOINTER_PLUS_EXPR(tree_node *exp);
+ Value *EmitPOINTER_PLUS_EXPR(tree_node *type, tree_node *op0, tree_node *op1);
// Exception Handling.
Value *EmitEXC_PTR_EXPR(tree_node *exp);
@@ -634,8 +639,9 @@
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);
+ void EmitCOMPLEX_EXPR(tree_node *op0, tree_node *op1, const MemRef *DestLoc);
+ Value *EmitComplexBinOp(tree_node *type, tree_code code, tree_node *op0,
+ tree_node *op1, const MemRef *DestLoc);
// L-Value Expressions.
LValue EmitLV_ARRAY_REF(tree_node *exp);
More information about the llvm-commits
mailing list