blob: 57a09e2d07f071f171b707bbbf76d212d354ca17 [file] [log] [blame]
Reid Spencere86bf512006-01-16 21:06:01 +00001//===-- AutoUpgrade.cpp - Implement auto-upgrade helper functions ---------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Reid Spencer and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the auto-upgrade helper functions
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Assembly/AutoUpgrade.h"
Jim Laskeyf4321a32006-03-13 13:07:37 +000015#include "llvm/Constants.h"
Reid Spencer4283ac72006-01-19 01:18:29 +000016#include "llvm/DerivedTypes.h"
Reid Spencere86bf512006-01-16 21:06:01 +000017#include "llvm/Function.h"
Reid Spencer4283ac72006-01-19 01:18:29 +000018#include "llvm/Module.h"
19#include "llvm/Instructions.h"
20#include "llvm/Intrinsics.h"
21#include "llvm/SymbolTable.h"
Reid Spencere86bf512006-01-16 21:06:01 +000022#include <iostream>
Reid Spencere86bf512006-01-16 21:06:01 +000023using namespace llvm;
24
Chris Lattnerffa987d2006-03-02 23:58:40 +000025static Function *getUpgradedUnaryFn(Function *F) {
Chris Lattner329b9512006-03-03 16:31:22 +000026 const std::string &Name = F->getName();
Chris Lattnerffa987d2006-03-02 23:58:40 +000027 Module *M = F->getParent();
28 switch (F->getReturnType()->getTypeID()) {
29 default: return 0;
30 case Type::UByteTyID:
31 case Type::SByteTyID:
Chris Lattner329b9512006-03-03 16:31:22 +000032 return M->getOrInsertFunction(Name+".i8",
Chris Lattnerffa987d2006-03-02 23:58:40 +000033 Type::UByteTy, Type::UByteTy, NULL);
34 case Type::UShortTyID:
35 case Type::ShortTyID:
Chris Lattner329b9512006-03-03 16:31:22 +000036 return M->getOrInsertFunction(Name+".i16",
Chris Lattnerffa987d2006-03-02 23:58:40 +000037 Type::UShortTy, Type::UShortTy, NULL);
38 case Type::UIntTyID:
39 case Type::IntTyID:
Chris Lattner329b9512006-03-03 16:31:22 +000040 return M->getOrInsertFunction(Name+".i32",
Chris Lattnerffa987d2006-03-02 23:58:40 +000041 Type::UIntTy, Type::UIntTy, NULL);
42 case Type::ULongTyID:
43 case Type::LongTyID:
Chris Lattner329b9512006-03-03 16:31:22 +000044 return M->getOrInsertFunction(Name+".i64",
Chris Lattnerffa987d2006-03-02 23:58:40 +000045 Type::ULongTy, Type::ULongTy, NULL);
Chris Lattner329b9512006-03-03 16:31:22 +000046 case Type::FloatTyID:
47 return M->getOrInsertFunction(Name+".f32",
48 Type::FloatTy, Type::FloatTy, NULL);
49 case Type::DoubleTyID:
50 return M->getOrInsertFunction(Name+".f64",
51 Type::DoubleTy, Type::DoubleTy, NULL);
52 }
Chris Lattnerffa987d2006-03-02 23:58:40 +000053}
54
55static Function *getUpgradedIntrinsic(Function *F) {
Reid Spencer4283ac72006-01-19 01:18:29 +000056 // If there's no function, we can't get the argument type.
Chris Lattnerffa987d2006-03-02 23:58:40 +000057 if (!F) return 0;
Reid Spencere86bf512006-01-16 21:06:01 +000058
59 // Get the Function's name.
60 const std::string& Name = F->getName();
61
62 // Quickly eliminate it, if it's not a candidate.
Chris Lattnerffa987d2006-03-02 23:58:40 +000063 if (Name.length() <= 8 || Name[0] != 'l' || Name[1] != 'l' ||
64 Name[2] != 'v' || Name[3] != 'm' || Name[4] != '.')
Reid Spencer4283ac72006-01-19 01:18:29 +000065 return 0;
Reid Spencere86bf512006-01-16 21:06:01 +000066
Chris Lattnerffa987d2006-03-02 23:58:40 +000067 Module *M = F->getParent();
Reid Spencere86bf512006-01-16 21:06:01 +000068 switch (Name[5]) {
Chris Lattnerffa987d2006-03-02 23:58:40 +000069 default: break;
70 case 'b':
71 if (Name == "llvm.bswap") return getUpgradedUnaryFn(F);
72 break;
73 case 'c':
74 if (Name == "llvm.ctpop" || Name == "llvm.ctlz" || Name == "llvm.cttz")
75 return getUpgradedUnaryFn(F);
76 break;
Jim Laskeyf4321a32006-03-13 13:07:37 +000077 case 'd':
78 if (Name == "llvm.dbg.stoppoint") {
Jim Laskeyd06b5fc2006-03-23 18:03:20 +000079 PointerType *ESP =
80 PointerType::get(StructType::get(std::vector<const Type*>()));
81 if (F->getReturnType() != Type::VoidTy ||
82 F->getFunctionType()->getParamType(2) != ESP) {
Jim Laskeyf4321a32006-03-13 13:07:37 +000083 return M->getOrInsertFunction(Name, Type::VoidTy,
Jim Laskeyd06b5fc2006-03-23 18:03:20 +000084 Type::UIntTy, Type::UIntTy, ESP, NULL);
Jim Laskeyf4321a32006-03-13 13:07:37 +000085 }
86 } else if (Name == "llvm.dbg.func.start") {
Jim Laskeyd06b5fc2006-03-23 18:03:20 +000087 PointerType *ESP =
88 PointerType::get(StructType::get(std::vector<const Type*>()));
89 if (F->getReturnType() != Type::VoidTy ||
90 F->getFunctionType()->getParamType(0) != ESP) {
91 return M->getOrInsertFunction(Name, Type::VoidTy, ESP, NULL);
Jim Laskeyf4321a32006-03-13 13:07:37 +000092 }
93 } else if (Name == "llvm.dbg.region.start") {
Jim Laskeyd06b5fc2006-03-23 18:03:20 +000094 PointerType *ESP =
95 PointerType::get(StructType::get(std::vector<const Type*>()));
96 if (F->getReturnType() != Type::VoidTy ||
97 F->getFunctionType()->getParamType(0) != ESP) {
98 return M->getOrInsertFunction(Name, Type::VoidTy, ESP, NULL);
Jim Laskeyf4321a32006-03-13 13:07:37 +000099 }
100 } else if (Name == "llvm.dbg.region.end") {
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000101 PointerType *ESP =
102 PointerType::get(StructType::get(std::vector<const Type*>()));
103 if (F->getReturnType() != Type::VoidTy ||
104 F->getFunctionType()->getParamType(0) != ESP) {
105 return M->getOrInsertFunction(Name, Type::VoidTy, ESP, NULL);
Jim Laskeyf4321a32006-03-13 13:07:37 +0000106 }
Jim Laskey5a588a92006-03-14 02:00:35 +0000107 } else if (Name == "llvm.dbg.declare") {
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000108 PointerType *ESP =
109 PointerType::get(StructType::get(std::vector<const Type*>()));
110 if (F->getReturnType() != Type::VoidTy ||
111 F->getFunctionType()->getParamType(0) != ESP ||
112 F->getFunctionType()->getParamType(1) != ESP) {
113 return M->getOrInsertFunction(Name, Type::VoidTy, ESP, ESP, NULL);
114 }
Jim Laskeyf4321a32006-03-13 13:07:37 +0000115 }
116 break;
Chris Lattnerffa987d2006-03-02 23:58:40 +0000117 case 'i':
118 if (Name == "llvm.isunordered" && F->arg_begin() != F->arg_end()) {
119 if (F->arg_begin()->getType() == Type::FloatTy)
120 return M->getOrInsertFunction(Name+".f32", F->getFunctionType());
121 if (F->arg_begin()->getType() == Type::DoubleTy)
122 return M->getOrInsertFunction(Name+".f64", F->getFunctionType());
123 }
124 break;
125 case 'm':
126 if (Name == "llvm.memcpy" || Name == "llvm.memset" ||
127 Name == "llvm.memmove") {
Chris Lattnera758b822006-03-09 18:42:10 +0000128 if (F->getFunctionType()->getParamType(2) == Type::UIntTy ||
129 F->getFunctionType()->getParamType(2) == Type::IntTy)
130 return M->getOrInsertFunction(Name+".i32", Type::VoidTy,
131 PointerType::get(Type::SByteTy),
132 F->getFunctionType()->getParamType(1),
133 Type::UIntTy, Type::UIntTy, NULL);
134 if (F->getFunctionType()->getParamType(2) == Type::ULongTy ||
135 F->getFunctionType()->getParamType(2) == Type::LongTy)
136 return M->getOrInsertFunction(Name+".i64", Type::VoidTy,
137 PointerType::get(Type::SByteTy),
138 F->getFunctionType()->getParamType(1),
139 Type::ULongTy, Type::UIntTy, NULL);
Chris Lattnerffa987d2006-03-02 23:58:40 +0000140 }
141 break;
142 case 's':
143 if (Name == "llvm.sqrt")
144 return getUpgradedUnaryFn(F);
145 break;
Reid Spencere86bf512006-01-16 21:06:01 +0000146 }
Reid Spencer4283ac72006-01-19 01:18:29 +0000147 return 0;
148}
149
Jim Laskeyf4321a32006-03-13 13:07:37 +0000150// Occasionally upgraded function call site arguments need to be permutated to
151// some new order. The result of getArgumentPermutation is an array of size
152// F->getFunctionType()getNumParams() indicating the new operand order. A value
153// of zero in the array indicates replacing with UndefValue for the arg type.
154// NULL is returned if there is no permutation. It's assumed that the function
155// name is in the form "llvm.?????"
Jim Laskey9b2b21b2006-03-23 20:13:25 +0000156static unsigned *getArgumentPermutation(Function* Fn, Function* NewFn) {
157 const std::string& Name = Fn->getName();
158 unsigned N = Fn->getFunctionType()->getNumParams();
159 unsigned M = NewFn->getFunctionType()->getNumParams();
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000160
Jim Laskeyf4321a32006-03-13 13:07:37 +0000161 switch (Name[5]) {
162 case 'd':
163 if (Name == "llvm.dbg.stoppoint") {
164 static unsigned Permutation[] = { 2, 3, 4 };
Jim Laskey9b2b21b2006-03-23 20:13:25 +0000165 assert(M == (sizeof(Permutation) / sizeof(unsigned)) &&
Jim Laskeyf4321a32006-03-13 13:07:37 +0000166 "Permutation is wrong length");
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000167 if (N == 4) return Permutation;
168 } else if (Name == "llvm.dbg.region.start") {
169 static unsigned Permutation[] = { 0 };
Jim Laskey9b2b21b2006-03-23 20:13:25 +0000170 assert(M == (sizeof(Permutation) / sizeof(unsigned)) &&
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000171 "Permutation is wrong length");
172 if (N == 0) return Permutation;
173 } else if (Name == "llvm.dbg.region.end") {
174 static unsigned Permutation[] = { 0 };
Jim Laskey9b2b21b2006-03-23 20:13:25 +0000175 assert(M == (sizeof(Permutation) / sizeof(unsigned)) &&
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000176 "Permutation is wrong length");
177 if (N == 0) return Permutation;
178 } else if (Name == "llvm.dbg.declare") {
179 static unsigned Permutation[] = { 0, 0 };
Jim Laskey9b2b21b2006-03-23 20:13:25 +0000180 assert(M == (sizeof(Permutation) / sizeof(unsigned)) &&
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000181 "Permutation is wrong length");
182 if (N == 0) return Permutation;
Jim Laskeyf4321a32006-03-13 13:07:37 +0000183 }
184 break;
185 }
186 return NULL;
187}
188
Reid Spencer4283ac72006-01-19 01:18:29 +0000189// UpgradeIntrinsicFunction - Convert overloaded intrinsic function names to
190// their non-overloaded variants by appending the appropriate suffix based on
191// the argument types.
Chris Lattnerffa987d2006-03-02 23:58:40 +0000192Function *llvm::UpgradeIntrinsicFunction(Function* F) {
Reid Spencer4283ac72006-01-19 01:18:29 +0000193 // See if its one of the name's we're interested in.
Chris Lattnerffa987d2006-03-02 23:58:40 +0000194 if (Function *R = getUpgradedIntrinsic(F)) {
Reid Spencer403d43a2006-04-12 17:56:16 +0000195 if (R->getName() != F->getName())
Reid Spencerdd0f8df2006-05-30 16:34:59 +0000196 std::cerr << "WARNING: change " << F->getName() << " to "
Reid Spencer403d43a2006-04-12 17:56:16 +0000197 << R->getName() << "\n";
Chris Lattnerffa987d2006-03-02 23:58:40 +0000198 return R;
Reid Spencer4283ac72006-01-19 01:18:29 +0000199 }
200 return 0;
201}
202
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000203// CastArg - Perform the appropriate cast of an upgraded argument.
204//
Jim Laskeye481b942006-03-25 18:40:47 +0000205static Value *CastArg(Value *Arg, const Type *Ty, Instruction *InsertBefore) {
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000206 if (Constant *C = dyn_cast<Constant>(Arg)) {
207 return ConstantExpr::getCast(C, Ty);
208 } else {
Reid Spencer3da59db2006-11-27 01:05:10 +0000209 return CastInst::createInferredCast(Arg, Ty, "autoupgrade_cast",
210 InsertBefore);
Jim Laskeyd06b5fc2006-03-23 18:03:20 +0000211 }
212}
Reid Spencere2a5fb02006-01-27 11:49:27 +0000213
Jim Laskeyf4321a32006-03-13 13:07:37 +0000214// UpgradeIntrinsicCall - In the BC reader, change a call to an intrinsic to be
215// a call to an upgraded intrinsic. We may have to permute the order or promote
216// some arguments with a cast.
Chris Lattnerffa987d2006-03-02 23:58:40 +0000217void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Reid Spencere2a5fb02006-01-27 11:49:27 +0000218 Function *F = CI->getCalledFunction();
Chris Lattnerffa987d2006-03-02 23:58:40 +0000219
220 const FunctionType *NewFnTy = NewFn->getFunctionType();
221 std::vector<Value*> Oprnds;
Jim Laskeyf4321a32006-03-13 13:07:37 +0000222
Jim Laskey9b2b21b2006-03-23 20:13:25 +0000223 unsigned *Permutation = getArgumentPermutation(F, NewFn);
Jim Laskeyf4321a32006-03-13 13:07:37 +0000224 unsigned N = NewFnTy->getNumParams();
225
226 if (Permutation) {
227 for (unsigned i = 0; i != N; ++i) {
228 unsigned p = Permutation[i];
229
230 if (p) {
231 Value *V = CI->getOperand(p);
232 if (V->getType() != NewFnTy->getParamType(i))
Jim Laskeye481b942006-03-25 18:40:47 +0000233 V = CastArg(V, NewFnTy->getParamType(i), CI);
Jim Laskeyf4321a32006-03-13 13:07:37 +0000234 Oprnds.push_back(V);
235 } else
236 Oprnds.push_back(UndefValue::get(NewFnTy->getParamType(i)));
237 }
Jim Laskey5a588a92006-03-14 02:00:35 +0000238 } else if (N) {
Jim Laskeyf4321a32006-03-13 13:07:37 +0000239 assert(N == (CI->getNumOperands() - 1) &&
240 "Upgraded function needs permutation");
241 for (unsigned i = 0; i != N; ++i) {
242 Value *V = CI->getOperand(i + 1);
243 if (V->getType() != NewFnTy->getParamType(i))
Jim Laskeye481b942006-03-25 18:40:47 +0000244 V = CastArg(V, NewFnTy->getParamType(i), CI);
Jim Laskeyf4321a32006-03-13 13:07:37 +0000245 Oprnds.push_back(V);
246 }
Reid Spencer4283ac72006-01-19 01:18:29 +0000247 }
Jim Laskeyf4321a32006-03-13 13:07:37 +0000248
249 bool NewIsVoid = NewFn->getReturnType() == Type::VoidTy;
250
251 CallInst *NewCI = new CallInst(NewFn, Oprnds,
252 NewIsVoid ? "" : CI->getName(),
253 CI);
Chris Lattnerffa987d2006-03-02 23:58:40 +0000254 NewCI->setTailCall(CI->isTailCall());
255 NewCI->setCallingConv(CI->getCallingConv());
256
257 if (!CI->use_empty()) {
Jim Laskeyf4321a32006-03-13 13:07:37 +0000258 if (NewIsVoid) {
259 CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
260 } else {
261 Instruction *RetVal = NewCI;
262
263 if (F->getReturnType() != NewFn->getReturnType()) {
Reid Spencer3da59db2006-11-27 01:05:10 +0000264 RetVal =
265 new BitCastInst(NewCI, F->getReturnType(), NewCI->getName(), CI);
Jim Laskeyf4321a32006-03-13 13:07:37 +0000266 NewCI->moveBefore(RetVal);
267 }
268
269 CI->replaceAllUsesWith(RetVal);
Chris Lattnerffa987d2006-03-02 23:58:40 +0000270 }
Chris Lattnerffa987d2006-03-02 23:58:40 +0000271 }
272 CI->eraseFromParent();
Reid Spencer4283ac72006-01-19 01:18:29 +0000273}
274
275bool llvm::UpgradeCallsToIntrinsic(Function* F) {
Jim Laskeyf4321a32006-03-13 13:07:37 +0000276 if (Function* NewFn = UpgradeIntrinsicFunction(F)) {
Reid Spencer4283ac72006-01-19 01:18:29 +0000277 for (Value::use_iterator UI = F->use_begin(), UE = F->use_end();
Chris Lattnerf690bc82006-01-20 18:04:43 +0000278 UI != UE; ) {
Jim Laskeyf4321a32006-03-13 13:07:37 +0000279 if (CallInst* CI = dyn_cast<CallInst>(*UI++))
280 UpgradeIntrinsicCall(CI, NewFn);
Reid Spencer4283ac72006-01-19 01:18:29 +0000281 }
Jim Laskeyf4321a32006-03-13 13:07:37 +0000282 if (NewFn != F)
Reid Spencer4283ac72006-01-19 01:18:29 +0000283 F->eraseFromParent();
284 return true;
285 }
Reid Spencere86bf512006-01-16 21:06:01 +0000286 return false;
287}