//
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();
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;
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),
if (OpNum == 0) {
PointerType *PTy = dyn_cast<PointerType>(Ty);
if (PTy == 0) return false; // Can't convert to a non-pointer type...
- MethodType *MTy = dyn_cast_or_null<MethodType>(PTy->getElementType());
+ MethodType *MTy = dyn_cast<MethodType>(PTy->getElementType());
if (MTy == 0) return false; // Can't convert to a non ptr to method...
// Perform sanity checks to make sure that new method type has the
// Okay, at this point, we know that the call and the method type match
// number of arguments. Now we see if we can convert the arguments
- // themselves.
+ // 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 methods but casted
+ // arguments if possible.
//
const MethodType::ParamTypes &PTs = MTy->getParamTypes();
for (unsigned i = 0, NA = PTs.size(); i < NA; ++i)
MethodType *NewTy = cast<MethodType>(NewPTy->getElementType());
const MethodType::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
+ // methods 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)
- Params[i] = ConvertExpressionToType(Params[i], PTs[i], VMC);
+ 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
} else { // Changing an argument, must be in vararg area