1 //===-- AutoUpgrade.cpp - Implement auto-upgrade helper functions ---------===//
3 // The LLVM Compiler Infrastructure
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.
8 //===----------------------------------------------------------------------===//
10 // This file implements the auto-upgrade helper functions
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Assembly/AutoUpgrade.h"
15 #include "llvm/Constants.h"
16 #include "llvm/DerivedTypes.h"
17 #include "llvm/Function.h"
18 #include "llvm/Module.h"
19 #include "llvm/Instructions.h"
20 #include "llvm/Intrinsics.h"
21 #include "llvm/SymbolTable.h"
25 static Function
*getUpgradedUnaryFn(Function
*F
) {
26 const std::string
&Name
= F
->getName();
27 Module
*M
= F
->getParent();
28 switch (F
->getReturnType()->getTypeID()) {
32 return M
->getOrInsertFunction(Name
+".i8",
33 Type::UByteTy
, Type::UByteTy
, NULL
);
34 case Type::UShortTyID
:
36 return M
->getOrInsertFunction(Name
+".i16",
37 Type::UShortTy
, Type::UShortTy
, NULL
);
40 return M
->getOrInsertFunction(Name
+".i32",
41 Type::UIntTy
, Type::UIntTy
, NULL
);
44 return M
->getOrInsertFunction(Name
+".i64",
45 Type::ULongTy
, Type::ULongTy
, NULL
);
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
);
55 static Function
*getUpgradedIntrinsic(Function
*F
) {
56 // If there's no function, we can't get the argument type.
59 // Get the Function's name.
60 const std::string
& Name
= F
->getName();
62 // Quickly eliminate it, if it's not a candidate.
63 if (Name
.length() <= 8 || Name
[0] != 'l' || Name
[1] != 'l' ||
64 Name
[2] != 'v' || Name
[3] != 'm' || Name
[4] != '.')
67 Module
*M
= F
->getParent();
71 if (Name
== "llvm.bswap") return getUpgradedUnaryFn(F
);
74 if (Name
== "llvm.ctpop" || Name
== "llvm.ctlz" || Name
== "llvm.cttz")
75 return getUpgradedUnaryFn(F
);
78 if (Name
== "llvm.dbg.stoppoint") {
80 PointerType::get(StructType::get(std::vector
<const Type
*>()));
81 if (F
->getReturnType() != Type::VoidTy
||
82 F
->getFunctionType()->getParamType(2) != ESP
) {
83 return M
->getOrInsertFunction(Name
, Type::VoidTy
,
84 Type::UIntTy
, Type::UIntTy
, ESP
, NULL
);
86 } else if (Name
== "llvm.dbg.func.start") {
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
);
93 } else if (Name
== "llvm.dbg.region.start") {
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
);
100 } else if (Name
== "llvm.dbg.region.end") {
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
);
107 } else if (Name
== "llvm.dbg.declare") {
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
);
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());
126 if (Name
== "llvm.memcpy" || Name
== "llvm.memset" ||
127 Name
== "llvm.memmove") {
128 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
);
143 if (Name
== "llvm.sqrt")
144 return getUpgradedUnaryFn(F
);
150 // 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.?????"
156 static 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();
163 if (Name
== "llvm.dbg.stoppoint") {
164 static unsigned Permutation
[] = { 2, 3, 4 };
165 assert(M
== (sizeof(Permutation
) / sizeof(unsigned)) &&
166 "Permutation is wrong length");
167 if (N
== 4) return Permutation
;
168 } else if (Name
== "llvm.dbg.region.start") {
169 static unsigned Permutation
[] = { 0 };
170 assert(M
== (sizeof(Permutation
) / sizeof(unsigned)) &&
171 "Permutation is wrong length");
172 if (N
== 0) return Permutation
;
173 } else if (Name
== "llvm.dbg.region.end") {
174 static unsigned Permutation
[] = { 0 };
175 assert(M
== (sizeof(Permutation
) / sizeof(unsigned)) &&
176 "Permutation is wrong length");
177 if (N
== 0) return Permutation
;
178 } else if (Name
== "llvm.dbg.declare") {
179 static unsigned Permutation
[] = { 0, 0 };
180 assert(M
== (sizeof(Permutation
) / sizeof(unsigned)) &&
181 "Permutation is wrong length");
182 if (N
== 0) return Permutation
;
189 // UpgradeIntrinsicFunction - Convert overloaded intrinsic function names to
190 // their non-overloaded variants by appending the appropriate suffix based on
191 // the argument types.
192 Function
*llvm::UpgradeIntrinsicFunction(Function
* F
) {
193 // See if its one of the name's we're interested in.
194 if (Function
*R
= getUpgradedIntrinsic(F
)) {
195 if (R
->getName() != F
->getName())
196 std::cerr
<< "WARNING: change " << F
->getName() << " to "
197 << R
->getName() << "\n";
203 // CastArg - Perform the appropriate cast of an upgraded argument.
205 static Value
*CastArg(Value
*Arg
, const Type
*Ty
, Instruction
*InsertBefore
) {
206 if (Constant
*C
= dyn_cast
<Constant
>(Arg
)) {
207 return ConstantExpr::getCast(C
, Ty
);
209 Value
*Cast
= new CastInst(Arg
, Ty
, "autoupgrade_cast", InsertBefore
);
214 // 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.
217 void llvm::UpgradeIntrinsicCall(CallInst
*CI
, Function
*NewFn
) {
218 Function
*F
= CI
->getCalledFunction();
220 const FunctionType
*NewFnTy
= NewFn
->getFunctionType();
221 std::vector
<Value
*> Oprnds
;
223 unsigned *Permutation
= getArgumentPermutation(F
, NewFn
);
224 unsigned N
= NewFnTy
->getNumParams();
227 for (unsigned i
= 0; i
!= N
; ++i
) {
228 unsigned p
= Permutation
[i
];
231 Value
*V
= CI
->getOperand(p
);
232 if (V
->getType() != NewFnTy
->getParamType(i
))
233 V
= CastArg(V
, NewFnTy
->getParamType(i
), CI
);
236 Oprnds
.push_back(UndefValue::get(NewFnTy
->getParamType(i
)));
239 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
))
244 V
= CastArg(V
, NewFnTy
->getParamType(i
), CI
);
249 bool NewIsVoid
= NewFn
->getReturnType() == Type::VoidTy
;
251 CallInst
*NewCI
= new CallInst(NewFn
, Oprnds
,
252 NewIsVoid
? "" : CI
->getName(),
254 NewCI
->setTailCall(CI
->isTailCall());
255 NewCI
->setCallingConv(CI
->getCallingConv());
257 if (!CI
->use_empty()) {
259 CI
->replaceAllUsesWith(UndefValue::get(CI
->getType()));
261 Instruction
*RetVal
= NewCI
;
263 if (F
->getReturnType() != NewFn
->getReturnType()) {
264 RetVal
= new CastInst(NewCI
, F
->getReturnType(),
265 NewCI
->getName(), CI
);
266 NewCI
->moveBefore(RetVal
);
269 CI
->replaceAllUsesWith(RetVal
);
272 CI
->eraseFromParent();
275 bool llvm::UpgradeCallsToIntrinsic(Function
* F
) {
276 if (Function
* NewFn
= UpgradeIntrinsicFunction(F
)) {
277 for (Value::use_iterator UI
= F
->use_begin(), UE
= F
->use_end();
279 if (CallInst
* CI
= dyn_cast
<CallInst
>(*UI
++))
280 UpgradeIntrinsicCall(CI
, NewFn
);
283 F
->eraseFromParent();