LLVM API Documentation

AutoUpgrade.cpp

Go to the documentation of this file.
00001 //===-- AutoUpgrade.cpp - Implement auto-upgrade helper functions ---------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by Reid Spencer and is distributed under the 
00006 // University of Illinois Open Source License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the auto-upgrade helper functions 
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Assembly/AutoUpgrade.h"
00015 #include "llvm/Constants.h"
00016 #include "llvm/DerivedTypes.h"
00017 #include "llvm/Function.h"
00018 #include "llvm/Module.h"
00019 #include "llvm/Instructions.h"
00020 #include "llvm/Intrinsics.h"
00021 #include "llvm/SymbolTable.h"
00022 #include <iostream>
00023 using namespace llvm;
00024 
00025 static Function *getUpgradedUnaryFn(Function *F) {
00026   const std::string &Name = F->getName();
00027   Module *M = F->getParent();
00028   switch (F->getReturnType()->getTypeID()) {
00029   default: return 0;
00030   case Type::UByteTyID:
00031   case Type::SByteTyID:
00032     return M->getOrInsertFunction(Name+".i8", 
00033                                   Type::UByteTy, Type::UByteTy, NULL);
00034   case Type::UShortTyID:
00035   case Type::ShortTyID:
00036     return M->getOrInsertFunction(Name+".i16", 
00037                                   Type::UShortTy, Type::UShortTy, NULL);
00038   case Type::UIntTyID:
00039   case Type::IntTyID:
00040     return M->getOrInsertFunction(Name+".i32", 
00041                                   Type::UIntTy, Type::UIntTy, NULL);
00042   case Type::ULongTyID:
00043   case Type::LongTyID:
00044     return M->getOrInsertFunction(Name+".i64",
00045                                   Type::ULongTy, Type::ULongTy, NULL);
00046   case Type::FloatTyID:
00047     return M->getOrInsertFunction(Name+".f32",
00048                                   Type::FloatTy, Type::FloatTy, NULL);
00049   case Type::DoubleTyID:
00050     return M->getOrInsertFunction(Name+".f64",
00051                                   Type::DoubleTy, Type::DoubleTy, NULL);
00052   }
00053 }
00054 
00055 static Function *getUpgradedIntrinsic(Function *F) {
00056   // If there's no function, we can't get the argument type.
00057   if (!F) return 0;
00058 
00059   // Get the Function's name.
00060   const std::string& Name = F->getName();
00061 
00062   // Quickly eliminate it, if it's not a candidate.
00063   if (Name.length() <= 8 || Name[0] != 'l' || Name[1] != 'l' || 
00064       Name[2] != 'v' || Name[3] != 'm' || Name[4] != '.')
00065     return 0;
00066 
00067   Module *M = F->getParent();
00068   switch (Name[5]) {
00069   default: break;
00070   case 'b':
00071     if (Name == "llvm.bswap") return getUpgradedUnaryFn(F);
00072     break;
00073   case 'c':
00074     if (Name == "llvm.ctpop" || Name == "llvm.ctlz" || Name == "llvm.cttz")
00075       return getUpgradedUnaryFn(F);
00076     break;
00077   case 'd':
00078     if (Name == "llvm.dbg.stoppoint") {
00079       PointerType *ESP =
00080                   PointerType::get(StructType::get(std::vector<const Type*>()));
00081       if (F->getReturnType() != Type::VoidTy ||
00082           F->getFunctionType()->getParamType(2) != ESP) {
00083         return M->getOrInsertFunction(Name, Type::VoidTy,
00084                                       Type::UIntTy, Type::UIntTy, ESP, NULL);
00085       }
00086     } else if (Name == "llvm.dbg.func.start") {
00087       PointerType *ESP =
00088                   PointerType::get(StructType::get(std::vector<const Type*>()));
00089       if (F->getReturnType()  != Type::VoidTy ||
00090           F->getFunctionType()->getParamType(0) != ESP) {
00091         return M->getOrInsertFunction(Name, Type::VoidTy, ESP, NULL);
00092       }
00093     } else if (Name == "llvm.dbg.region.start") {
00094       PointerType *ESP =
00095                   PointerType::get(StructType::get(std::vector<const Type*>()));
00096       if (F->getReturnType() != Type::VoidTy ||
00097           F->getFunctionType()->getParamType(0) != ESP) {
00098         return M->getOrInsertFunction(Name, Type::VoidTy,  ESP, NULL);
00099       }
00100     } else if (Name == "llvm.dbg.region.end") {
00101       PointerType *ESP =
00102                   PointerType::get(StructType::get(std::vector<const Type*>()));
00103       if (F->getReturnType() != Type::VoidTy ||
00104           F->getFunctionType()->getParamType(0) != ESP) {
00105          return M->getOrInsertFunction(Name, Type::VoidTy,  ESP, NULL);
00106       }
00107     } else if (Name == "llvm.dbg.declare") {
00108       PointerType *ESP =
00109                   PointerType::get(StructType::get(std::vector<const Type*>()));
00110       if (F->getReturnType() != Type::VoidTy ||
00111           F->getFunctionType()->getParamType(0) != ESP ||
00112           F->getFunctionType()->getParamType(1) != ESP) {
00113         return M->getOrInsertFunction(Name, Type::VoidTy, ESP, ESP, NULL);
00114       }
00115     }
00116     break;
00117   case 'i':
00118     if (Name == "llvm.isunordered" && F->arg_begin() != F->arg_end()) {
00119       if (F->arg_begin()->getType() == Type::FloatTy)
00120         return M->getOrInsertFunction(Name+".f32", F->getFunctionType());
00121       if (F->arg_begin()->getType() == Type::DoubleTy)
00122         return M->getOrInsertFunction(Name+".f64", F->getFunctionType());
00123     }
00124     break;
00125   case 'm':
00126     if (Name == "llvm.memcpy" || Name == "llvm.memset" || 
00127         Name == "llvm.memmove") {
00128       if (F->getFunctionType()->getParamType(2) == Type::UIntTy ||
00129           F->getFunctionType()->getParamType(2) == Type::IntTy)
00130         return M->getOrInsertFunction(Name+".i32", Type::VoidTy,
00131                                       PointerType::get(Type::SByteTy),
00132                                       F->getFunctionType()->getParamType(1),
00133                                       Type::UIntTy, Type::UIntTy, NULL);
00134       if (F->getFunctionType()->getParamType(2) == Type::ULongTy ||
00135           F->getFunctionType()->getParamType(2) == Type::LongTy)
00136         return M->getOrInsertFunction(Name+".i64", Type::VoidTy,
00137                                       PointerType::get(Type::SByteTy),
00138                                       F->getFunctionType()->getParamType(1),
00139                                       Type::ULongTy, Type::UIntTy, NULL);
00140     }
00141     break;
00142   case 's':
00143     if (Name == "llvm.sqrt")
00144       return getUpgradedUnaryFn(F);
00145     break;
00146   }
00147   return 0;
00148 }
00149 
00150 // Occasionally upgraded function call site arguments need to be permutated to
00151 // some new order.  The result of getArgumentPermutation is an array of size 
00152 // F->getFunctionType()getNumParams() indicating the new operand order.  A value
00153 // of zero in the array indicates replacing with UndefValue for the arg type.
00154 // NULL is returned if there is no permutation.  It's assumed that the function
00155 // name is in the form "llvm.?????"
00156 static unsigned *getArgumentPermutation(Function* Fn, Function* NewFn) {
00157   const std::string& Name = Fn->getName();
00158   unsigned N = Fn->getFunctionType()->getNumParams();
00159   unsigned M = NewFn->getFunctionType()->getNumParams();
00160   
00161   switch (Name[5]) {
00162   case 'd':
00163     if (Name == "llvm.dbg.stoppoint") {
00164       static unsigned Permutation[] = { 2, 3, 4 };
00165       assert(M == (sizeof(Permutation) / sizeof(unsigned)) &&
00166              "Permutation is wrong length");
00167       if (N == 4) return Permutation;
00168     } else if (Name == "llvm.dbg.region.start") {
00169       static unsigned Permutation[] = { 0 };
00170       assert(M == (sizeof(Permutation) / sizeof(unsigned)) &&
00171              "Permutation is wrong length");
00172       if (N == 0) return Permutation;
00173     } else if (Name == "llvm.dbg.region.end") {
00174       static unsigned Permutation[] = { 0 };
00175       assert(M == (sizeof(Permutation) / sizeof(unsigned)) &&
00176              "Permutation is wrong length");
00177       if (N == 0) return Permutation;
00178     } else if (Name == "llvm.dbg.declare") {
00179       static unsigned Permutation[] = { 0, 0 };
00180       assert(M == (sizeof(Permutation) / sizeof(unsigned)) &&
00181              "Permutation is wrong length");
00182       if (N == 0) return Permutation;
00183     }
00184     break;
00185   }
00186   return NULL;
00187 }
00188 
00189 // UpgradeIntrinsicFunction - Convert overloaded intrinsic function names to
00190 // their non-overloaded variants by appending the appropriate suffix based on
00191 // the argument types.
00192 Function *llvm::UpgradeIntrinsicFunction(Function* F) {
00193   // See if its one of the name's we're interested in.
00194   if (Function *R = getUpgradedIntrinsic(F)) {
00195     if (R->getName() != F->getName())
00196       std::cerr << "WARNING: change " << F->getName() << " to "
00197                 << R->getName() << "\n";
00198     return R;
00199   }
00200   return 0;
00201 }
00202 
00203 // CastArg - Perform the appropriate cast of an upgraded argument.
00204 //
00205 static Value *CastArg(Value *Arg, const Type *Ty, Instruction *InsertBefore) {
00206   if (Constant *C = dyn_cast<Constant>(Arg)) {
00207     return ConstantExpr::getCast(C, Ty);
00208   } else {
00209     Value *Cast = new CastInst(Arg, Ty, "autoupgrade_cast", InsertBefore);
00210     return Cast;
00211   }
00212 }
00213 
00214 // UpgradeIntrinsicCall - In the BC reader, change a call to an intrinsic to be
00215 // a call to an upgraded intrinsic.  We may have to permute the order or promote
00216 // some arguments with a cast.
00217 void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
00218   Function *F = CI->getCalledFunction();
00219 
00220   const FunctionType *NewFnTy = NewFn->getFunctionType();
00221   std::vector<Value*> Oprnds;
00222   
00223   unsigned *Permutation = getArgumentPermutation(F, NewFn);
00224   unsigned N = NewFnTy->getNumParams();
00225 
00226   if (Permutation) {
00227     for (unsigned i = 0; i != N; ++i) {
00228       unsigned p = Permutation[i];
00229       
00230       if (p) {
00231         Value *V = CI->getOperand(p);
00232         if (V->getType() != NewFnTy->getParamType(i))
00233           V = CastArg(V, NewFnTy->getParamType(i), CI);
00234         Oprnds.push_back(V);
00235       } else
00236         Oprnds.push_back(UndefValue::get(NewFnTy->getParamType(i)));
00237     }
00238   } else if (N) {
00239     assert(N == (CI->getNumOperands() - 1) &&
00240            "Upgraded function needs permutation");
00241     for (unsigned i = 0; i != N; ++i) {
00242       Value *V = CI->getOperand(i + 1);
00243       if (V->getType() != NewFnTy->getParamType(i))
00244         V = CastArg(V, NewFnTy->getParamType(i), CI);
00245       Oprnds.push_back(V);
00246     }
00247   }
00248   
00249   bool NewIsVoid = NewFn->getReturnType() == Type::VoidTy;
00250   
00251   CallInst *NewCI = new CallInst(NewFn, Oprnds,
00252                                  NewIsVoid ? "" : CI->getName(),
00253                                  CI);
00254   NewCI->setTailCall(CI->isTailCall());
00255   NewCI->setCallingConv(CI->getCallingConv());
00256   
00257   if (!CI->use_empty()) {
00258     if (NewIsVoid) {
00259       CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
00260     } else {
00261       Instruction *RetVal = NewCI;
00262       
00263       if (F->getReturnType() != NewFn->getReturnType()) {
00264         RetVal = new CastInst(NewCI, F->getReturnType(), 
00265                               NewCI->getName(), CI);
00266         NewCI->moveBefore(RetVal);
00267       }
00268       
00269       CI->replaceAllUsesWith(RetVal);
00270     }
00271   }
00272   CI->eraseFromParent();
00273 }
00274 
00275 bool llvm::UpgradeCallsToIntrinsic(Function* F) {
00276   if (Function* NewFn = UpgradeIntrinsicFunction(F)) {
00277     for (Value::use_iterator UI = F->use_begin(), UE = F->use_end();
00278          UI != UE; ) {
00279       if (CallInst* CI = dyn_cast<CallInst>(*UI++)) 
00280         UpgradeIntrinsicCall(CI, NewFn);
00281     }
00282     if (NewFn != F)
00283       F->eraseFromParent();
00284     return true;
00285   }
00286   return false;
00287 }