//===----------------------------------------------------------------------===//
#include "TransformInternals.h"
-#include "llvm/Method.h"
#include "llvm/iOther.h"
#include "llvm/iPHINode.h"
#include "llvm/iMemory.h"
-#include "llvm/ConstantVals.h"
-#include "llvm/Optimizations/ConstantHandling.h"
-#include "llvm/Optimizations/DCE.h"
+#include "llvm/ConstantHandling.h"
#include "llvm/Analysis/Expressions.h"
#include "Support/STLExtras.h"
-#include <map>
#include <algorithm>
-
-#include "llvm/Assembly/Writer.h"
+#include <iostream>
+using std::cerr;
//#define DEBUG_EXPR_CONVERT 1
//
static bool MallocConvertableToType(MallocInst *MI, const Type *Ty,
ValueTypeCache &CTMap) {
- if (!MI->isArrayAllocation() || // No array allocation?
- !isa<PointerType>(Ty)) return false; // Malloc always returns pointers
+ if (!isa<PointerType>(Ty)) return false; // Malloc always returns pointers
// Deal with the type to allocate, not the pointer type...
Ty = cast<PointerType>(Ty)->getElementType();
analysis::ExprType Expr = analysis::ClassifyExpression(MI->getArraySize());
// Get information about the base datatype being allocated, before & after
- unsigned ReqTypeSize = TD.getTypeSize(Ty);
+ int ReqTypeSize = TD.getTypeSize(Ty);
unsigned OldTypeSize = TD.getTypeSize(MI->getType()->getElementType());
// Must have a scale or offset to analyze it...
- if (!Expr.Offset && !Expr.Scale) return false;
+ if (!Expr.Offset && !Expr.Scale && OldTypeSize == 1) return false;
// Get the offset and scale of the allocation...
int OffsetVal = Expr.Offset ? getConstantValue(Expr.Offset) : 0;
int ScaleVal = Expr.Scale ? getConstantValue(Expr.Scale) : (Expr.Var ? 1 : 0);
- if (ScaleVal < 0 || OffsetVal < 0) {
- cerr << "malloc of a negative number???\n";
- return false;
- }
// The old type might not be of unit size, take old size into consideration
// here...
- unsigned Offset = (unsigned)OffsetVal * OldTypeSize;
- unsigned Scale = (unsigned)ScaleVal * OldTypeSize;
+ int Offset = OffsetVal * OldTypeSize;
+ int Scale = ScaleVal * OldTypeSize;
// In order to be successful, both the scale and the offset must be a multiple
// of the requested data type's size.
}
static Instruction *ConvertMallocToType(MallocInst *MI, const Type *Ty,
- const string &Name, ValueMapCache &VMC){
+ const std::string &Name,
+ ValueMapCache &VMC){
BasicBlock *BB = MI->getParent();
BasicBlock::iterator It = BB->end();
// it can convert the value...
//
if (Constant *CPV = dyn_cast<Constant>(V))
- if (opt::ConstantFoldCastInstruction(CPV, Ty))
+ if (ConstantFoldCastInstruction(CPV, Ty))
return true; // Don't worry about deallocating, it's a constant.
return false; // Otherwise, we can't convert!
// index array. If there are, check to see if removing them causes us to
// get to the right type...
//
- vector<Value*> Indices = GEP->copyIndices();
+ std::vector<Value*> Indices = GEP->copyIndices();
const Type *BaseType = GEP->getPointerOperand()->getType();
const Type *ElTy = 0;
// Check to see if 'N' is an expression that can be converted to
// the appropriate size... if so, allow it.
//
- vector<Value*> Indices;
+ std::vector<Value*> Indices;
const Type *ElTy = ConvertableToGEP(PTy, I->getOperand(1), Indices);
- if (ElTy) {
- assert(ElTy == PVTy && "Internal error, setup wrong!");
+ if (ElTy == PVTy) {
if (!ExpressionConvertableToType(I->getOperand(0),
PointerType::get(ElTy), CTMap))
return false; // Can't continue, ExConToTy might have polluted set!
ValueMapCache::ExprMapTy::iterator VMCI = VMC.ExprMap.find(V);
if (VMCI != VMC.ExprMap.end()) {
assert(VMCI->second->getType() == Ty);
+
+ if (Instruction *I = dyn_cast<Instruction>(V))
+ ValueHandle IHandle(VMC, I); // Remove I if it is unused now!
+
return VMCI->second;
}
if (Constant *CPV = cast<Constant>(V)) {
// Constants are converted by constant folding the cast that is required.
// We assume here that all casts are implemented for constant prop.
- Value *Result = opt::ConstantFoldCastInstruction(CPV, Ty);
+ Value *Result = ConstantFoldCastInstruction(CPV, Ty);
assert(Result && "ConstantFoldCastInstruction Failed!!!");
assert(Result->getType() == Ty && "Const prop of cast failed!");
BasicBlock *BB = I->getParent();
BasicBlock::InstListType &BIL = BB->getInstList();
- string Name = I->getName(); if (!Name.empty()) I->setName("");
+ std::string Name = I->getName(); if (!Name.empty()) I->setName("");
Instruction *Res; // Result of conversion
ValueHandle IHandle(VMC, I); // Prevent I from being removed!
- Constant *Dummy = Constant::getNullConstant(Ty);
+ Constant *Dummy = Constant::getNullValue(Ty);
switch (I->getOpcode()) {
case Instruction::Cast:
LoadInst *LI = cast<LoadInst>(I);
assert(!LI->hasIndices() || AllIndicesZero(LI));
- Res = new LoadInst(Constant::getNullConstant(PointerType::get(Ty)), Name);
+ Res = new LoadInst(Constant::getNullValue(PointerType::get(Ty)), Name);
VMC.ExprMap[I] = Res;
Res->setOperand(0, ConvertExpressionToType(LI->getPointerOperand(),
PointerType::get(Ty), VMC));
// index array. If there are, check to see if removing them causes us to
// get to the right type...
//
- vector<Value*> Indices = GEP->copyIndices();
+ std::vector<Value*> Indices = GEP->copyIndices();
const Type *BaseType = GEP->getPointerOperand()->getType();
const Type *PVTy = cast<PointerType>(Ty)->getElementType();
Res = 0;
// Check to see if 'N' is an expression that can be converted to
// the appropriate size... if so, allow it.
//
- vector<Value*> Indices;
+ std::vector<Value*> Indices;
const Type *ElTy = ConvertableToGEP(NewSrcTy, I->getOperand(1),
Indices, &It);
if (ElTy) {
assert(ElTy == PVTy && "Internal error, setup wrong!");
- Res = new GetElementPtrInst(Constant::getNullConstant(NewSrcTy),
+ Res = new GetElementPtrInst(Constant::getNullValue(NewSrcTy),
Indices, Name);
VMC.ExprMap[I] = Res;
Res->setOperand(0, ConvertExpressionToType(I->getOperand(0),
//
if (Res == 0) {
const PointerType *NewSrcTy = PointerType::get(PVTy);
- Res = new GetElementPtrInst(Constant::getNullConstant(NewSrcTy),
+ Res = new GetElementPtrInst(Constant::getNullValue(NewSrcTy),
GEP->copyIndices(), Name);
VMC.ExprMap[I] = Res;
Res->setOperand(0, ConvertExpressionToType(I->getOperand(0),
// It is safe to convert the specified value to the specified type IFF all of
// the uses of the value can be converted to accept the new typed value.
//
- for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I)
- if (!OperandConvertableToType(*I, V, Ty, ConvertedTypes))
- return false;
+ if (V->getType() != Ty) {
+ for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I)
+ if (!OperandConvertableToType(*I, V, Ty, ConvertedTypes))
+ return false;
+ }
return true;
}
I->getType() == I->getOperand(0)->getType())
return false;
+ // Do not allow a 'cast ushort %V to uint' to have it's first operand be
+ // converted to a 'short' type. Doing so changes the way sign promotion
+ // happens, and breaks things. Only allow the cast to take place if the
+ // signedness doesn't change... or if the current cast is not a lossy
+ // conversion.
+ //
+ if (!I->getType()->isLosslesslyConvertableTo(I->getOperand(0)->getType()) &&
+ I->getOperand(0)->getType()->isSigned() != Ty->isSigned())
+ return false;
#if 1
// We also do not allow conversion of a cast that casts from a ptr to array
case Instruction::Add:
if (isa<PointerType>(Ty)) {
Value *IndexVal = I->getOperand(V == I->getOperand(0) ? 1 : 0);
- vector<Value*> Indices;
+ std::vector<Value*> Indices;
if (const Type *ETy = ConvertableToGEP(Ty, IndexVal, Indices)) {
const Type *RetTy = PointerType::get(ETy);
// They could be loading the first element of a composite type...
if (const CompositeType *CT = dyn_cast<CompositeType>(LoadedTy)) {
unsigned Offset = 0; // No offset, get first leaf.
- vector<Value*> Indices; // Discarded...
+ std::vector<Value*> Indices; // Discarded...
LoadedTy = getStructOffsetType(CT, Offset, Indices, false);
assert(Offset == 0 && "Offset changed from zero???");
}
if (SI->hasIndices()) return false;
if (V == I->getOperand(0)) {
+ ValueTypeCache::iterator CTMI = CTMap.find(I->getOperand(1));
+ if (CTMI != CTMap.end()) { // Operand #1 is in the table already?
+ // If so, check to see if it's Ty*, or, more importantly, if it is a
+ // pointer to a structure where the first element is a Ty... this code
+ // is neccesary because we might be trying to change the source and
+ // destination type of the store (they might be related) and the dest
+ // pointer type might be a pointer to structure. Below we allow pointer
+ // to structures where the 0th element is compatible with the value,
+ // now we have to support the symmetrical part of this.
+ //
+ const Type *ElTy = cast<PointerType>(CTMI->second)->getElementType();
+
+ // Already a pointer to what we want? Trivially accept...
+ if (ElTy == Ty) return true;
+
+ // Tricky case now, if the destination is a pointer to structure,
+ // obviously the source is not allowed to be a structure (cannot copy
+ // a whole structure at a time), so the level raiser must be trying to
+ // store into the first field. Check for this and allow it now:
+ //
+ if (StructType *SElTy = dyn_cast<StructType>(ElTy)) {
+ unsigned Offset = 0;
+ std::vector<Value*> Indices;
+ ElTy = getStructOffsetType(ElTy, Offset, Indices, false);
+ assert(Offset == 0 && "Offset changed!");
+ if (ElTy == 0) // Element at offset zero in struct doesn't exist!
+ return false; // Can only happen for {}*
+
+ if (ElTy == Ty) // Looks like the 0th element of structure is
+ return true; // compatible! Accept now!
+
+ // Otherwise we know that we can't work, so just stop trying now.
+ return false;
+ }
+ }
+
// Can convert the store if we can convert the pointer operand to match
// the new value type...
return ExpressionConvertableToType(I->getOperand(1), PointerType::get(Ty),
const Type *ElTy = PT->getElementType();
assert(V == I->getOperand(1));
+ if (isa<StructType>(ElTy)) {
+ // We can change the destination pointer if we can store our first
+ // argument into the first element of the structure...
+ //
+ unsigned Offset = 0;
+ std::vector<Value*> Indices;
+ ElTy = getStructOffsetType(ElTy, Offset, Indices, false);
+ assert(Offset == 0 && "Offset changed!");
+ if (ElTy == 0) // Element at offset zero in struct doesn't exist!
+ return false; // Can only happen for {}*
+ }
+
// Must move the same amount of data...
if (TD.getTypeSize(ElTy) != TD.getTypeSize(I->getOperand(0)->getType()))
return false;
// Check to see if the second argument is an expression that can
// be converted to the appropriate size... if so, allow it.
//
- vector<Value*> Indices;
+ std::vector<Value*> Indices;
const Type *ElTy = ConvertableToGEP(Ty, Index, Indices);
delete TempScale; // Free our temporary multiply if we made it
assert (OI != I->op_end() && "Not using value!");
unsigned OpNum = OI - I->op_begin();
- if (OpNum == 0)
- return false; // Can't convert method pointer type yet. FIXME
+ // Are we trying to change the function pointer value to a new type?
+ if (OpNum == 0) {
+ PointerType *PTy = dyn_cast<PointerType>(Ty);
+ if (PTy == 0) return false; // Can't convert to a non-pointer type...
+ FunctionType *MTy = dyn_cast<FunctionType>(PTy->getElementType());
+ if (MTy == 0) return false; // Can't convert to a non ptr to function...
+
+ // Perform sanity checks to make sure that new function type has the
+ // correct number of arguments...
+ //
+ unsigned NumArgs = I->getNumOperands()-1; // Don't include function ptr
+
+ // Cannot convert to a type that requires more fixed arguments than
+ // the call provides...
+ //
+ if (NumArgs < MTy->getParamTypes().size()) return false;
+
+ // Unless this is a vararg function type, we cannot provide more arguments
+ // than are desired...
+ //
+ if (!MTy->isVarArg() && NumArgs > MTy->getParamTypes().size())
+ return false;
+
+ // Okay, at this point, we know that the call and the function type match
+ // number of arguments. Now we see if we can convert the arguments
+ // themselves. Note that we do not require operands to be convertable,
+ // we can insert casts if they are convertible but not compatible. The
+ // reason for this is that we prefer to have resolved functions but casted
+ // arguments if possible.
+ //
+ const FunctionType::ParamTypes &PTs = MTy->getParamTypes();
+ for (unsigned i = 0, NA = PTs.size(); i < NA; ++i)
+ if (!PTs[i]->isLosslesslyConvertableTo(I->getOperand(i+1)->getType()))
+ return false; // Operands must have compatible types!
+
+ // Okay, at this point, we know that all of the arguments can be
+ // converted. We succeed if we can change the return type if
+ // neccesary...
+ //
+ return ValueConvertableToType(I, MTy->getReturnType(), CTMap);
+ }
const PointerType *MPtr = cast<PointerType>(I->getOperand(0)->getType());
- const MethodType *MTy = cast<MethodType>(MPtr->getElementType());
+ const FunctionType *MTy = cast<FunctionType>(MPtr->getElementType());
if (!MTy->isVarArg()) return false;
if ((OpNum-1) < MTy->getParamTypes().size())
return false; // It's not in the varargs section...
// If we get this far, we know the value is in the varargs section of the
- // method! We can convert if we don't reinterpret the value...
+ // function! We can convert if we don't reinterpret the value...
//
return Ty->isLosslesslyConvertableTo(V->getType());
}
BasicBlock *BB = I->getParent();
BasicBlock::InstListType &BIL = BB->getInstList();
- string Name = I->getName(); if (!Name.empty()) I->setName("");
+ std::string Name = I->getName(); if (!Name.empty()) I->setName("");
Instruction *Res; // Result of conversion
//cerr << endl << endl << "Type:\t" << Ty << "\nInst: " << I << "BB Before: " << BB << endl;
const Type *NewTy = NewVal->getType();
Constant *Dummy = (NewTy != Type::VoidTy) ?
- Constant::getNullConstant(NewTy) : 0;
+ Constant::getNullValue(NewTy) : 0;
switch (I->getOpcode()) {
case Instruction::Cast:
case Instruction::Add:
if (isa<PointerType>(NewTy)) {
Value *IndexVal = I->getOperand(OldVal == I->getOperand(0) ? 1 : 0);
- vector<Value*> Indices;
+ std::vector<Value*> Indices;
BasicBlock::iterator It = find(BIL.begin(), BIL.end(), I);
if (const Type *ETy = ConvertableToGEP(NewTy, IndexVal, Indices, &It)) {
// If successful, convert the add to a GEP
- const Type *RetTy = PointerType::get(ETy);
+ //const Type *RetTy = PointerType::get(ETy);
// First operand is actually the given pointer...
Res = new GetElementPtrInst(NewVal, Indices, Name);
assert(cast<PointerType>(Res->getType())->getElementType() == ETy &&
const Type *LoadedTy =
cast<PointerType>(NewVal->getType())->getElementType();
- vector<Value*> Indices;
+ std::vector<Value*> Indices;
Indices.push_back(ConstantUInt::get(Type::UIntTy, 0));
if (const CompositeType *CT = dyn_cast<CompositeType>(LoadedTy)) {
case Instruction::Store: {
if (I->getOperand(0) == OldVal) { // Replace the source value
const PointerType *NewPT = PointerType::get(NewTy);
- Res = new StoreInst(NewVal, Constant::getNullConstant(NewPT));
+ Res = new StoreInst(NewVal, Constant::getNullValue(NewPT));
VMC.ExprMap[I] = Res;
Res->setOperand(1, ConvertExpressionToType(I->getOperand(1), NewPT, VMC));
} else { // Replace the source pointer
const Type *ValTy = cast<PointerType>(NewTy)->getElementType();
- vector<Value*> Indices;
-#if 0
- Indices.push_back(ConstantUInt::get(Type::UIntTy, 0));
- while (ArrayType *AT = dyn_cast<ArrayType>(ValTy)) {
+ std::vector<Value*> Indices;
+
+ if (isa<StructType>(ValTy)) {
+ unsigned Offset = 0;
Indices.push_back(ConstantUInt::get(Type::UIntTy, 0));
- ValTy = AT->getElementType();
+ ValTy = getStructOffsetType(ValTy, Offset, Indices, false);
+ assert(Offset == 0 && ValTy);
}
-#endif
- Res = new StoreInst(Constant::getNullConstant(ValTy), NewVal, Indices);
+
+ Res = new StoreInst(Constant::getNullValue(ValTy), NewVal, Indices);
VMC.ExprMap[I] = Res;
Res->setOperand(0, ConvertExpressionToType(I->getOperand(0), ValTy, VMC));
}
// Perform the conversion now...
//
- vector<Value*> Indices;
+ std::vector<Value*> Indices;
const Type *ElTy = ConvertableToGEP(NewVal->getType(), Index, Indices, &It);
assert(ElTy != 0 && "GEP Conversion Failure!");
Res = new GetElementPtrInst(NewVal, Indices, Name);
// Check to see if the second argument is an expression that can
// be converted to the appropriate size... if so, allow it.
//
- vector<Value*> Indices;
+ std::vector<Value*> Indices;
const Type *ElTy = ConvertableToGEP(NewVal->getType(), I->getOperand(1),
Indices, &It);
assert(ElTy != 0 && "GEP Conversion Failure!");
case Instruction::Call: {
Value *Meth = I->getOperand(0);
- vector<Value*> Params(I->op_begin()+1, I->op_end());
+ std::vector<Value*> Params(I->op_begin()+1, I->op_end());
+
+ if (Meth == OldVal) { // Changing the function pointer?
+ PointerType *NewPTy = cast<PointerType>(NewVal->getType());
+ FunctionType *NewTy = cast<FunctionType>(NewPTy->getElementType());
+ const FunctionType::ParamTypes &PTs = NewTy->getParamTypes();
+
+ // Get an iterator to the call instruction so that we can insert casts for
+ // operands if needbe. Note that we do not require operands to be
+ // convertable, we can insert casts if they are convertible but not
+ // compatible. The reason for this is that we prefer to have resolved
+ // functions but casted arguments if possible.
+ //
+ BasicBlock::iterator It = find(BIL.begin(), BIL.end(), I);
+
+ // Convert over all of the call operands to their new types... but only
+ // convert over the part that is not in the vararg section of the call.
+ //
+ for (unsigned i = 0; i < PTs.size(); ++i)
+ if (Params[i]->getType() != PTs[i]) {
+ // Create a cast to convert it to the right type, we know that this
+ // is a lossless cast...
+ //
+ Params[i] = new CastInst(Params[i], PTs[i], "call.resolve.cast");
+ It = BIL.insert(It, cast<Instruction>(Params[i]))+1;
+ }
+ Meth = NewVal; // Update call destination to new value
- vector<Value*>::iterator OI = find(Params.begin(), Params.end(), OldVal);
- assert (OI != Params.end() && "Not using value!");
+ } else { // Changing an argument, must be in vararg area
+ std::vector<Value*>::iterator OI =
+ find(Params.begin(), Params.end(), OldVal);
+ assert (OI != Params.end() && "Not using value!");
+
+ *OI = NewVal;
+ }
- *OI = NewVal;
Res = new CallInst(Meth, Params, Name);
break;
}
#endif
for (User::op_iterator OI = I->op_begin(), OE = I->op_end();
- OI != OE; ++OI) {
- Instruction *U = dyn_cast<Instruction>(*OI);
- if (U) {
+ OI != OE; ++OI)
+ if (Instruction *U = dyn_cast<Instruction>(*OI)) {
*OI = 0;
- RecursiveDelete(Cache, dyn_cast<Instruction>(U));
+ RecursiveDelete(Cache, U);
}
- }
I->getParent()->getInstList().remove(I);