blob: e330dda7d03022eb65f8d7821f055e7ca2c08aac [file] [log] [blame]
Reed Kotler783c7942013-05-10 22:25:39 +00001//===---- Mips16HardFloat.cpp for Mips16 Hard Float --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a pass needed for Mips16 Hard Float
11//
12//===----------------------------------------------------------------------===//
13
Reed Kotler783c7942013-05-10 22:25:39 +000014#include "Mips16HardFloat.h"
Benjamin Kramera52f6962015-03-09 15:50:58 +000015#include "MipsTargetMachine.h"
Reed Kotler783c7942013-05-10 22:25:39 +000016#include "llvm/IR/Module.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000017#include "llvm/IR/Value.h"
Reed Kotler783c7942013-05-10 22:25:39 +000018#include "llvm/Support/Debug.h"
19#include "llvm/Support/raw_ostream.h"
Reed Kotlerd265e882013-08-11 21:30:27 +000020#include <algorithm>
Reed Kotler783c7942013-05-10 22:25:39 +000021#include <string>
Benjamin Kramera52f6962015-03-09 15:50:58 +000022using namespace llvm;
Reed Kotler783c7942013-05-10 22:25:39 +000023
Chandler Carruth84e68b22014-04-22 02:41:26 +000024#define DEBUG_TYPE "mips16-hard-float"
25
Reed Kotler2c4657d2013-05-14 02:00:24 +000026static void inlineAsmOut
27 (LLVMContext &C, StringRef AsmString, BasicBlock *BB ) {
28 std::vector<llvm::Type *> AsmArgTypes;
29 std::vector<llvm::Value*> AsmArgs;
30 llvm::FunctionType *AsmFTy =
31 llvm::FunctionType::get(Type::getVoidTy(C),
32 AsmArgTypes, false);
33 llvm::InlineAsm *IA =
34 llvm::InlineAsm::get(AsmFTy, AsmString, "", true,
35 /* IsAlignStack */ false,
36 llvm::InlineAsm::AD_ATT);
37 CallInst::Create(IA, AsmArgs, "", BB);
38}
39
40namespace {
41
42class InlineAsmHelper {
43 LLVMContext &C;
44 BasicBlock *BB;
45public:
46 InlineAsmHelper(LLVMContext &C_, BasicBlock *BB_) :
47 C(C_), BB(BB_) {
48 }
49
50 void Out(StringRef AsmString) {
51 inlineAsmOut(C, AsmString, BB);
52 }
53
54};
55}
Reed Kotler783c7942013-05-10 22:25:39 +000056//
57// Return types that matter for hard float are:
58// float, double, complex float, and complex double
59//
60enum FPReturnVariant {
61 FRet, DRet, CFRet, CDRet, NoFPRet
62};
63
64//
65// Determine which FP return type this function has
66//
67static FPReturnVariant whichFPReturnVariant(Type *T) {
68 switch (T->getTypeID()) {
69 case Type::FloatTyID:
70 return FRet;
71 case Type::DoubleTyID:
72 return DRet;
73 case Type::StructTyID:
74 if (T->getStructNumElements() != 2)
75 break;
76 if ((T->getContainedType(0)->isFloatTy()) &&
77 (T->getContainedType(1)->isFloatTy()))
78 return CFRet;
79 if ((T->getContainedType(0)->isDoubleTy()) &&
80 (T->getContainedType(1)->isDoubleTy()))
81 return CDRet;
82 break;
83 default:
84 break;
85 }
86 return NoFPRet;
87}
88
89//
Reed Kotler2c4657d2013-05-14 02:00:24 +000090// Parameter type that matter are float, (float, float), (float, double),
91// double, (double, double), (double, float)
92//
93enum FPParamVariant {
94 FSig, FFSig, FDSig,
95 DSig, DDSig, DFSig, NoSig
96};
97
98// which floating point parameter signature variant we are dealing with
99//
100typedef Type::TypeID TypeID;
101const Type::TypeID FloatTyID = Type::FloatTyID;
102const Type::TypeID DoubleTyID = Type::DoubleTyID;
103
104static FPParamVariant whichFPParamVariantNeeded(Function &F) {
105 switch (F.arg_size()) {
106 case 0:
107 return NoSig;
108 case 1:{
109 TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID();
110 switch (ArgTypeID) {
111 case FloatTyID:
112 return FSig;
113 case DoubleTyID:
114 return DSig;
115 default:
116 return NoSig;
117 }
118 }
119 default: {
120 TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID();
121 TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID();
122 switch(ArgTypeID0) {
123 case FloatTyID: {
124 switch (ArgTypeID1) {
125 case FloatTyID:
126 return FFSig;
127 case DoubleTyID:
128 return FDSig;
129 default:
130 return FSig;
131 }
132 }
133 case DoubleTyID: {
134 switch (ArgTypeID1) {
135 case FloatTyID:
136 return DFSig;
137 case DoubleTyID:
138 return DDSig;
139 default:
140 return DSig;
141 }
142 }
143 default:
144 return NoSig;
145 }
146 }
147 }
148 llvm_unreachable("can't get here");
149}
150
151// Figure out if we need float point based on the function parameters.
152// We need to move variables in and/or out of floating point
153// registers because of the ABI
154//
155static bool needsFPStubFromParams(Function &F) {
156 if (F.arg_size() >=1) {
157 Type *ArgType = F.getFunctionType()->getParamType(0);
158 switch (ArgType->getTypeID()) {
159 case Type::FloatTyID:
160 case Type::DoubleTyID:
161 return true;
162 default:
163 break;
164 }
165 }
166 return false;
167}
168
169static bool needsFPReturnHelper(Function &F) {
170 Type* RetType = F.getReturnType();
171 return whichFPReturnVariant(RetType) != NoFPRet;
172}
173
Reed Kotler2500bd62013-12-18 23:57:48 +0000174static bool needsFPReturnHelper(const FunctionType &FT) {
175 Type* RetType = FT.getReturnType();
176 return whichFPReturnVariant(RetType) != NoFPRet;
177}
178
Reed Kotler2c4657d2013-05-14 02:00:24 +0000179static bool needsFPHelperFromSig(Function &F) {
180 return needsFPStubFromParams(F) || needsFPReturnHelper(F);
181}
182
183//
184// We swap between FP and Integer registers to allow Mips16 and Mips32 to
185// interoperate
186//
187
Reed Kotlercad47f02013-05-14 02:13:45 +0000188static void swapFPIntParams
189 (FPParamVariant PV, Module *M, InlineAsmHelper &IAH,
190 bool LE, bool ToFP) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000191 //LLVMContext &Context = M->getContext();
192 std::string MI = ToFP? "mtc1 ": "mfc1 ";
193 switch (PV) {
194 case FSig:
195 IAH.Out(MI + "$$4,$$f12");
196 break;
197 case FFSig:
198 IAH.Out(MI +"$$4,$$f12");
199 IAH.Out(MI + "$$5,$$f14");
200 break;
201 case FDSig:
202 IAH.Out(MI + "$$4,$$f12");
203 if (LE) {
204 IAH.Out(MI + "$$6,$$f14");
205 IAH.Out(MI + "$$7,$$f15");
206 } else {
207 IAH.Out(MI + "$$7,$$f14");
208 IAH.Out(MI + "$$6,$$f15");
209 }
210 break;
211 case DSig:
212 if (LE) {
213 IAH.Out(MI + "$$4,$$f12");
214 IAH.Out(MI + "$$5,$$f13");
215 } else {
216 IAH.Out(MI + "$$5,$$f12");
217 IAH.Out(MI + "$$4,$$f13");
218 }
219 break;
220 case DDSig:
221 if (LE) {
222 IAH.Out(MI + "$$4,$$f12");
223 IAH.Out(MI + "$$5,$$f13");
224 IAH.Out(MI + "$$6,$$f14");
225 IAH.Out(MI + "$$7,$$f15");
226 } else {
227 IAH.Out(MI + "$$5,$$f12");
228 IAH.Out(MI + "$$4,$$f13");
229 IAH.Out(MI + "$$7,$$f14");
230 IAH.Out(MI + "$$6,$$f15");
231 }
232 break;
233 case DFSig:
234 if (LE) {
235 IAH.Out(MI + "$$4,$$f12");
236 IAH.Out(MI + "$$5,$$f13");
237 } else {
238 IAH.Out(MI + "$$5,$$f12");
239 IAH.Out(MI + "$$4,$$f13");
240 }
241 IAH.Out(MI + "$$6,$$f14");
242 break;
243 case NoSig:
244 return;
245 }
246}
247//
248// Make sure that we know we already need a stub for this function.
249// Having called needsFPHelperFromSig
250//
Reed Kotler4cdaa7d2014-02-14 19:16:39 +0000251static void assureFPCallStub(Function &F, Module *M,
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000252 const MipsTargetMachine &TM) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000253 // for now we only need them for static relocation
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000254 if (TM.getRelocationModel() == Reloc::PIC_)
Reed Kotler2c4657d2013-05-14 02:00:24 +0000255 return;
256 LLVMContext &Context = M->getContext();
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000257 bool LE = TM.isLittleEndian();
Reed Kotler2c4657d2013-05-14 02:00:24 +0000258 std::string Name = F.getName();
259 std::string SectionName = ".mips16.call.fp." + Name;
Reed Kotler302ae6b2013-08-01 02:26:31 +0000260 std::string StubName = "__call_stub_fp_" + Name;
Reed Kotler2c4657d2013-05-14 02:00:24 +0000261 //
262 // see if we already have the stub
263 //
264 Function *FStub = M->getFunction(StubName);
265 if (FStub && !FStub->isDeclaration()) return;
266 FStub = Function::Create(F.getFunctionType(),
267 Function::InternalLinkage, StubName, M);
268 FStub->addFnAttr("mips16_fp_stub");
269 FStub->addFnAttr(llvm::Attribute::Naked);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000270 FStub->addFnAttr(llvm::Attribute::NoInline);
Reed Kotler2c4657d2013-05-14 02:00:24 +0000271 FStub->addFnAttr(llvm::Attribute::NoUnwind);
272 FStub->addFnAttr("nomips16");
273 FStub->setSection(SectionName);
274 BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
275 InlineAsmHelper IAH(Context, BB);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000276 IAH.Out(".set reorder");
Reed Kotler2c4657d2013-05-14 02:00:24 +0000277 FPReturnVariant RV = whichFPReturnVariant(FStub->getReturnType());
278 FPParamVariant PV = whichFPParamVariantNeeded(F);
279 swapFPIntParams(PV, M, IAH, LE, true);
280 if (RV != NoFPRet) {
281 IAH.Out("move $$18, $$31");
282 IAH.Out("jal " + Name);
283 } else {
284 IAH.Out("lui $$25,%hi(" + Name + ")");
285 IAH.Out("addiu $$25,$$25,%lo(" + Name + ")" );
286 }
287 switch (RV) {
288 case FRet:
289 IAH.Out("mfc1 $$2,$$f0");
290 break;
291 case DRet:
292 if (LE) {
293 IAH.Out("mfc1 $$2,$$f0");
294 IAH.Out("mfc1 $$3,$$f1");
295 } else {
296 IAH.Out("mfc1 $$3,$$f0");
297 IAH.Out("mfc1 $$2,$$f1");
298 }
299 break;
300 case CFRet:
301 if (LE) {
302 IAH.Out("mfc1 $$2,$$f0");
303 IAH.Out("mfc1 $$3,$$f2");
304 } else {
305 IAH.Out("mfc1 $$3,$$f0");
306 IAH.Out("mfc1 $$3,$$f2");
307 }
308 break;
309 case CDRet:
310 if (LE) {
311 IAH.Out("mfc1 $$4,$$f2");
312 IAH.Out("mfc1 $$5,$$f3");
313 IAH.Out("mfc1 $$2,$$f0");
314 IAH.Out("mfc1 $$3,$$f1");
315
316 } else {
317 IAH.Out("mfc1 $$5,$$f2");
318 IAH.Out("mfc1 $$4,$$f3");
319 IAH.Out("mfc1 $$3,$$f0");
320 IAH.Out("mfc1 $$2,$$f1");
321 }
322 break;
323 case NoFPRet:
324 break;
325 }
326 if (RV != NoFPRet)
327 IAH.Out("jr $$18");
328 else
329 IAH.Out("jr $$25");
330 new UnreachableInst(Context, BB);
331}
332
333//
Reed Kotler5fdadce2013-09-01 04:12:59 +0000334// Functions that are llvm intrinsics and don't need helpers.
Reed Kotlerd265e882013-08-11 21:30:27 +0000335//
Benjamin Kramerc9b7d472013-08-12 09:37:29 +0000336static const char *IntrinsicInline[] =
Reed Kotler5fdadce2013-09-01 04:12:59 +0000337 {"fabs",
Reed Kotler339c7412013-10-08 19:55:01 +0000338 "fabsf",
Reed Kotler5fdadce2013-09-01 04:12:59 +0000339 "llvm.ceil.f32", "llvm.ceil.f64",
340 "llvm.copysign.f32", "llvm.copysign.f64",
341 "llvm.cos.f32", "llvm.cos.f64",
342 "llvm.exp.f32", "llvm.exp.f64",
343 "llvm.exp2.f32", "llvm.exp2.f64",
344 "llvm.fabs.f32", "llvm.fabs.f64",
345 "llvm.floor.f32", "llvm.floor.f64",
346 "llvm.fma.f32", "llvm.fma.f64",
347 "llvm.log.f32", "llvm.log.f64",
348 "llvm.log10.f32", "llvm.log10.f64",
349 "llvm.nearbyint.f32", "llvm.nearbyint.f64",
350 "llvm.pow.f32", "llvm.pow.f64",
351 "llvm.powi.f32", "llvm.powi.f64",
352 "llvm.rint.f32", "llvm.rint.f64",
353 "llvm.round.f32", "llvm.round.f64",
354 "llvm.sin.f32", "llvm.sin.f64",
355 "llvm.sqrt.f32", "llvm.sqrt.f64",
356 "llvm.trunc.f32", "llvm.trunc.f64",
357 };
Reed Kotlerd265e882013-08-11 21:30:27 +0000358
Benjamin Kramerc9b7d472013-08-12 09:37:29 +0000359static bool isIntrinsicInline(Function *F) {
Benjamin Kramer502b9e12014-04-12 16:15:53 +0000360 return std::binary_search(std::begin(IntrinsicInline),
361 std::end(IntrinsicInline), F->getName());
Reed Kotlerd265e882013-08-11 21:30:27 +0000362}
363//
Reed Kotler783c7942013-05-10 22:25:39 +0000364// Returns of float, double and complex need to be handled with a helper
Reed Kotler515e9372013-05-16 02:17:42 +0000365// function.
Reed Kotler783c7942013-05-10 22:25:39 +0000366//
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000367static bool fixupFPReturnAndCall(Function &F, Module *M,
368 const MipsTargetMachine &TM) {
Reed Kotler783c7942013-05-10 22:25:39 +0000369 bool Modified = false;
370 LLVMContext &C = M->getContext();
371 Type *MyVoid = Type::getVoidTy(C);
372 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
373 for (BasicBlock::iterator I = BB->begin(), E = BB->end();
374 I != E; ++I) {
375 Instruction &Inst = *I;
376 if (const ReturnInst *RI = dyn_cast<ReturnInst>(I)) {
377 Value *RVal = RI->getReturnValue();
378 if (!RVal) continue;
379 //
380 // If there is a return value and it needs a helper function,
381 // figure out which one and add a call before the actual
382 // return to this helper. The purpose of the helper is to move
383 // floating point values from their soft float return mapping to
384 // where they would have been mapped to in floating point registers.
385 //
386 Type *T = RVal->getType();
387 FPReturnVariant RV = whichFPReturnVariant(T);
388 if (RV == NoFPRet) continue;
389 static const char* Helper[NoFPRet] =
390 {"__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",
391 "__mips16_ret_dc"};
392 const char *Name = Helper[RV];
393 AttributeSet A;
394 Value *Params[] = {RVal};
395 Modified = true;
396 //
397 // These helper functions have a different calling ABI so
398 // this __Mips16RetHelper indicates that so that later
399 // during call setup, the proper call lowering to the helper
400 // functions will take place.
401 //
402 A = A.addAttribute(C, AttributeSet::FunctionIndex,
403 "__Mips16RetHelper");
404 A = A.addAttribute(C, AttributeSet::FunctionIndex,
405 Attribute::ReadNone);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000406 A = A.addAttribute(C, AttributeSet::FunctionIndex,
407 Attribute::NoInline);
Reid Kleckner343c3952014-11-20 23:51:47 +0000408 Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, nullptr));
Reed Kotler783c7942013-05-10 22:25:39 +0000409 CallInst::Create(F, Params, "", &Inst );
Reed Kotler2c4657d2013-05-14 02:00:24 +0000410 } else if (const CallInst *CI = dyn_cast<CallInst>(I)) {
Reed Kotler2500bd62013-12-18 23:57:48 +0000411 const Value* V = CI->getCalledValue();
Craig Topper062a2ba2014-04-25 05:30:21 +0000412 const Type* T = nullptr;
Reed Kotler2500bd62013-12-18 23:57:48 +0000413 if (V) T = V->getType();
Craig Topper062a2ba2014-04-25 05:30:21 +0000414 const PointerType *PFT=nullptr;
Reed Kotler2500bd62013-12-18 23:57:48 +0000415 if (T) PFT = dyn_cast<PointerType>(T);
Craig Topper062a2ba2014-04-25 05:30:21 +0000416 const FunctionType *FT=nullptr;
Reed Kotler2500bd62013-12-18 23:57:48 +0000417 if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType());
Reed Kotler0ff40012013-12-10 14:29:38 +0000418 Function *F_ = CI->getCalledFunction();
Reed Kotler2500bd62013-12-18 23:57:48 +0000419 if (FT && needsFPReturnHelper(*FT) &&
420 !(F_ && isIntrinsicInline(F_))) {
421 Modified=true;
422 F.addFnAttr("saveS2");
423 }
Reed Kotler0ff40012013-12-10 14:29:38 +0000424 if (F_ && !isIntrinsicInline(F_)) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000425 // pic mode calls are handled by already defined
426 // helper functions
Reed Kotler0ff40012013-12-10 14:29:38 +0000427 if (needsFPReturnHelper(*F_)) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000428 Modified=true;
Reed Kotler0ff40012013-12-10 14:29:38 +0000429 F.addFnAttr("saveS2");
430 }
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000431 if (TM.getRelocationModel() != Reloc::PIC_ ) {
Reed Kotler0ff40012013-12-10 14:29:38 +0000432 if (needsFPHelperFromSig(*F_)) {
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000433 assureFPCallStub(*F_, M, TM);
Reed Kotler0ff40012013-12-10 14:29:38 +0000434 Modified=true;
435 }
Reed Kotler2c4657d2013-05-14 02:00:24 +0000436 }
437 }
Reed Kotler783c7942013-05-10 22:25:39 +0000438 }
439 }
440 return Modified;
441}
442
Reed Kotler515e9372013-05-16 02:17:42 +0000443static void createFPFnStub(Function *F, Module *M, FPParamVariant PV,
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000444 const MipsTargetMachine &TM) {
445 bool PicMode = TM.getRelocationModel() == Reloc::PIC_;
446 bool LE = TM.isLittleEndian();
Reed Kotler515e9372013-05-16 02:17:42 +0000447 LLVMContext &Context = M->getContext();
448 std::string Name = F->getName();
449 std::string SectionName = ".mips16.fn." + Name;
450 std::string StubName = "__fn_stub_" + Name;
Reed Kotlera6ce7972013-09-25 20:58:50 +0000451 std::string LocalName = "$$__fn_local_" + Name;
Reed Kotler515e9372013-05-16 02:17:42 +0000452 Function *FStub = Function::Create
453 (F->getFunctionType(),
Reed Kotler302ae6b2013-08-01 02:26:31 +0000454 Function::InternalLinkage, StubName, M);
Reed Kotler515e9372013-05-16 02:17:42 +0000455 FStub->addFnAttr("mips16_fp_stub");
456 FStub->addFnAttr(llvm::Attribute::Naked);
457 FStub->addFnAttr(llvm::Attribute::NoUnwind);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000458 FStub->addFnAttr(llvm::Attribute::NoInline);
Reed Kotler515e9372013-05-16 02:17:42 +0000459 FStub->addFnAttr("nomips16");
460 FStub->setSection(SectionName);
461 BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
462 InlineAsmHelper IAH(Context, BB);
Reed Kotler515e9372013-05-16 02:17:42 +0000463 if (PicMode) {
464 IAH.Out(".set noreorder");
Reed Kotlera6ce7972013-09-25 20:58:50 +0000465 IAH.Out(".cpload $$25");
Reed Kotler515e9372013-05-16 02:17:42 +0000466 IAH.Out(".set reorder");
467 IAH.Out(".reloc 0,R_MIPS_NONE," + Name);
468 IAH.Out("la $$25," + LocalName);
469 }
Reed Kotler78fb2912013-09-21 01:37:52 +0000470 else {
Reed Kotlera6ce7972013-09-25 20:58:50 +0000471 IAH.Out("la $$25," + Name);
Reed Kotler78fb2912013-09-21 01:37:52 +0000472 }
Reed Kotler515e9372013-05-16 02:17:42 +0000473 swapFPIntParams(PV, M, IAH, LE, false);
474 IAH.Out("jr $$25");
475 IAH.Out(LocalName + " = " + Name);
476 new UnreachableInst(FStub->getContext(), BB);
477}
478
Reed Kotlerc03807a2013-08-30 19:40:56 +0000479//
480// remove the use-soft-float attribute
481//
482static void removeUseSoftFloat(Function &F) {
483 AttributeSet A;
484 DEBUG(errs() << "removing -use-soft-float\n");
485 A = A.addAttribute(F.getContext(), AttributeSet::FunctionIndex,
486 "use-soft-float", "false");
487 F.removeAttributes(AttributeSet::FunctionIndex, A);
488 if (F.hasFnAttribute("use-soft-float")) {
489 DEBUG(errs() << "still has -use-soft-float\n");
490 }
491 F.addAttributes(AttributeSet::FunctionIndex, A);
492}
493
Benjamin Kramera52f6962015-03-09 15:50:58 +0000494namespace {
495class Mips16HardFloat : public ModulePass {
496public:
497 static char ID;
498
499 Mips16HardFloat(MipsTargetMachine &TM_) : ModulePass(ID), TM(TM_) {}
500
501 const char *getPassName() const override { return "MIPS16 Hard Float Pass"; }
502 bool runOnModule(Module &M) override;
503
504protected:
505 const MipsTargetMachine &TM;
506};
507} // namespace
Reed Kotler783c7942013-05-10 22:25:39 +0000508
509//
510// This pass only makes sense when the underlying chip has floating point but
511// we are compiling as mips16.
512// For all mips16 functions (that are not stubs we have already generated), or
513// declared via attributes as nomips16, we must:
514// 1) fixup all returns of float, double, single and double complex
515// by calling a helper function before the actual return.
Reed Kotler4cdaa7d2014-02-14 19:16:39 +0000516// 2) generate helper functions (stubs) that can be called by mips32
517// functions that will move parameters passed normally passed in
518// floating point
Reed Kotler515e9372013-05-16 02:17:42 +0000519// registers the soft float equivalents.
Reed Kotler783c7942013-05-10 22:25:39 +0000520// 3) in the case of static relocation, generate helper functions so that
521// mips16 functions can call extern functions of unknown type (mips16 or
Reed Kotler515e9372013-05-16 02:17:42 +0000522// mips32).
Reed Kotler783c7942013-05-10 22:25:39 +0000523// 4) TBD. For pic, calls to extern functions of unknown type are handled by
524// predefined helper functions in libc but this work is currently done
525// during call lowering but it should be moved here in the future.
526//
527bool Mips16HardFloat::runOnModule(Module &M) {
528 DEBUG(errs() << "Run on Module Mips16HardFloat\n");
529 bool Modified = false;
530 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
Reed Kotlerc03807a2013-08-30 19:40:56 +0000531 if (F->hasFnAttribute("nomips16") &&
532 F->hasFnAttribute("use-soft-float")) {
533 removeUseSoftFloat(*F);
534 continue;
535 }
Reed Kotler783c7942013-05-10 22:25:39 +0000536 if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") ||
537 F->hasFnAttribute("nomips16")) continue;
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000538 Modified |= fixupFPReturnAndCall(*F, &M, TM);
Reed Kotler515e9372013-05-16 02:17:42 +0000539 FPParamVariant V = whichFPParamVariantNeeded(*F);
540 if (V != NoSig) {
541 Modified = true;
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000542 createFPFnStub(F, &M, V, TM);
Reed Kotler515e9372013-05-16 02:17:42 +0000543 }
Reed Kotler783c7942013-05-10 22:25:39 +0000544 }
545 return Modified;
546}
547
548char Mips16HardFloat::ID = 0;
549
Reed Kotler783c7942013-05-10 22:25:39 +0000550ModulePass *llvm::createMips16HardFloat(MipsTargetMachine &TM) {
551 return new Mips16HardFloat(TM);
552}
553