- }
- return Changed;
-}
-
-
-
-
-// DoInsertArrayCast - If the argument value has a pointer type, and if the
-// argument value is used as an array, insert a cast before the specified
-// basic block iterator that casts the value to an array pointer. Return the
-// new cast instruction (in the CastResult var), or null if no cast is inserted.
-//
-static bool DoInsertArrayCast(Value *V, BasicBlock *BB,
- BasicBlock::iterator InsertBefore) {
- const PointerType *ThePtrType = dyn_cast<PointerType>(V->getType());
- if (!ThePtrType) return false;
-
- const Type *ElTy = ThePtrType->getValueType();
- if (isa<MethodType>(ElTy) || isa<ArrayType>(ElTy)) return false;
-
- unsigned ElementSize = TD.getTypeSize(ElTy);
- bool InsertCast = false;
-
- for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
- Instruction *Inst = cast<Instruction>(*I);
- switch (Inst->getOpcode()) {
- case Instruction::Cast: // There is already a cast instruction!
- if (const PointerType *PT = dyn_cast<const PointerType>(Inst->getType()))
- if (const ArrayType *AT = dyn_cast<const ArrayType>(PT->getValueType()))
- if (AT->getElementType() == ThePtrType->getValueType()) {
- // Cast already exists! Don't mess around with it.
- return false; // No changes made to program though...
- }
- break;
- case Instruction::Add: { // Analyze pointer arithmetic...
- Value *OtherOp = Inst->getOperand(Inst->getOperand(0) == V);
- analysis::ExprType Expr = analysis::ClassifyExpression(OtherOp);
-
- // This looks like array addressing iff:
- // A. The constant of the index is larger than the size of the element
- // type.
- // B. The scale factor is >= the size of the type.
- //
- if (Expr.Offset && getConstantValue(Expr.Offset) >= (int)ElementSize) // A
- InsertCast = true;
-
- if (Expr.Scale && getConstantValue(Expr.Scale) >= (int)ElementSize) // B
- InsertCast = true;
-
- break;
- }
- default: break; // Not an interesting use...
- }
- }
-
- if (!InsertCast) return false; // There is no reason to insert a cast!
-
- // Calculate the destination pointer type
- const PointerType *DestTy = PointerType::get(ArrayType::get(ElTy));
-
- // Check to make sure that all uses of the value can be converted over to use
- // the newly typed value.
- //
- ValueTypeCache ConvertedTypes;
- if (!ValueConvertableToType(V, DestTy, ConvertedTypes)) {
- cerr << "FAILED to convert types of values for " << V << "\n";
- ConvertedTypes.clear();
- ValueConvertableToType(V, DestTy, ConvertedTypes);
- return false;
- }
- ConvertedTypes.clear();
-
- // Insert a cast!
- CastInst *TheCast =
- new CastInst(ConstPoolVal::getNullConstant(V->getType()), DestTy,
- V->getName());
- BB->getInstList().insert(InsertBefore, TheCast);
-
- cerr << "Inserting cast for " << V << endl;
-
- // Convert users of the old value over to use the cast result...
- ValueMapCache VMC;
- ConvertValueToNewType(V, TheCast, VMC);
-
- // The cast is the only thing that is allowed to reference the value...
- TheCast->setOperand(0, V);
-
- cerr << "Inserted ptr-array cast: " << TheCast;
- return true; // Made a change!
-}
-
-
-// DoInsertArrayCasts - Loop over all "incoming" values in the specified method,
-// inserting a cast for pointer values that are used as arrays. For our
-// purposes, an incoming value is considered to be either a value that is
-// either a method parameter, or a pointer returned from a function call.
-//
-static bool DoInsertArrayCasts(Method *M) {
- assert(!M->isExternal() && "Can't handle external methods!");
-
- // Insert casts for all arguments to the function...
- bool Changed = false;
- BasicBlock *CurBB = M->front();
-
- for (Method::ArgumentListType::iterator AI = M->getArgumentList().begin(),
- AE = M->getArgumentList().end(); AI != AE; ++AI) {
-
- Changed |= DoInsertArrayCast(*AI, CurBB, CurBB->begin());
- }
-
- // TODO: insert casts for alloca, malloc, and function call results. Also,
- // look for pointers that already have casts, to add to the map.