blob: 893fc7cdf473b123efd6b23cfb06679bef755d11 [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
Benjamin Kramer16132e62015-03-23 18:07:13 +000014#include "MipsTargetMachine.h"
Reed Kotler783c7942013-05-10 22:25:39 +000015#include "llvm/IR/Module.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/IR/Value.h"
Reed Kotler783c7942013-05-10 22:25:39 +000017#include "llvm/Support/Debug.h"
Benjamin Kramer16132e62015-03-23 18:07:13 +000018#include "llvm/Support/raw_ostream.h"
Reed Kotlerd265e882013-08-11 21:30:27 +000019#include <algorithm>
Reed Kotler783c7942013-05-10 22:25:39 +000020#include <string>
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +000021
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 +000026namespace {
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +000027 class Mips16HardFloat : public ModulePass {
28 public:
29 static char ID;
Reed Kotler2c4657d2013-05-14 02:00:24 +000030
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +000031 Mips16HardFloat(MipsTargetMachine &TM_) : ModulePass(ID), TM(TM_) {}
Reed Kotler2c4657d2013-05-14 02:00:24 +000032
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +000033 const char *getPassName() const override {
34 return "MIPS16 Hard Float Pass";
35 }
Reed Kotler2c4657d2013-05-14 02:00:24 +000036
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +000037 bool runOnModule(Module &M) override;
38
39 protected:
40 const MipsTargetMachine &TM;
41 };
42
43 class InlineAsmHelper {
44 LLVMContext &C;
45 BasicBlock *BB;
46 public:
47 InlineAsmHelper(LLVMContext &C_, BasicBlock *BB_) :
48 C(C_), BB(BB_) {
49 }
50
51 void Out(StringRef AsmString) {
52 std::vector<llvm::Type *> AsmArgTypes;
53 std::vector<llvm::Value*> AsmArgs;
54
55 llvm::FunctionType *AsmFTy = llvm::FunctionType::get(Type::getVoidTy(C),
56 AsmArgTypes, false);
57 llvm::InlineAsm *IA = llvm::InlineAsm::get(AsmFTy, AsmString, "", true,
58 /* IsAlignStack */ false,
59 llvm::InlineAsm::AD_ATT);
60 CallInst::Create(IA, AsmArgs, "", BB);
61 }
62 };
63
64 char Mips16HardFloat::ID = 0;
Alexander Kornienkof00654e2015-06-23 09:49:53 +000065}
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +000066
Reed Kotler783c7942013-05-10 22:25:39 +000067//
68// Return types that matter for hard float are:
69// float, double, complex float, and complex double
70//
71enum FPReturnVariant {
72 FRet, DRet, CFRet, CDRet, NoFPRet
73};
74
75//
76// Determine which FP return type this function has
77//
78static FPReturnVariant whichFPReturnVariant(Type *T) {
79 switch (T->getTypeID()) {
80 case Type::FloatTyID:
81 return FRet;
82 case Type::DoubleTyID:
83 return DRet;
84 case Type::StructTyID:
85 if (T->getStructNumElements() != 2)
86 break;
87 if ((T->getContainedType(0)->isFloatTy()) &&
88 (T->getContainedType(1)->isFloatTy()))
89 return CFRet;
90 if ((T->getContainedType(0)->isDoubleTy()) &&
91 (T->getContainedType(1)->isDoubleTy()))
92 return CDRet;
93 break;
94 default:
95 break;
96 }
97 return NoFPRet;
98}
99
100//
Reed Kotler2c4657d2013-05-14 02:00:24 +0000101// Parameter type that matter are float, (float, float), (float, double),
102// double, (double, double), (double, float)
103//
104enum FPParamVariant {
105 FSig, FFSig, FDSig,
106 DSig, DDSig, DFSig, NoSig
107};
108
109// which floating point parameter signature variant we are dealing with
110//
111typedef Type::TypeID TypeID;
112const Type::TypeID FloatTyID = Type::FloatTyID;
113const Type::TypeID DoubleTyID = Type::DoubleTyID;
114
115static FPParamVariant whichFPParamVariantNeeded(Function &F) {
116 switch (F.arg_size()) {
117 case 0:
118 return NoSig;
119 case 1:{
120 TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID();
121 switch (ArgTypeID) {
122 case FloatTyID:
123 return FSig;
124 case DoubleTyID:
125 return DSig;
126 default:
127 return NoSig;
128 }
129 }
130 default: {
131 TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID();
132 TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID();
133 switch(ArgTypeID0) {
134 case FloatTyID: {
135 switch (ArgTypeID1) {
136 case FloatTyID:
137 return FFSig;
138 case DoubleTyID:
139 return FDSig;
140 default:
141 return FSig;
142 }
143 }
144 case DoubleTyID: {
145 switch (ArgTypeID1) {
146 case FloatTyID:
147 return DFSig;
148 case DoubleTyID:
149 return DDSig;
150 default:
151 return DSig;
152 }
153 }
154 default:
155 return NoSig;
156 }
157 }
158 }
159 llvm_unreachable("can't get here");
160}
161
162// Figure out if we need float point based on the function parameters.
163// We need to move variables in and/or out of floating point
164// registers because of the ABI
165//
166static bool needsFPStubFromParams(Function &F) {
167 if (F.arg_size() >=1) {
168 Type *ArgType = F.getFunctionType()->getParamType(0);
169 switch (ArgType->getTypeID()) {
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000170 case Type::FloatTyID:
171 case Type::DoubleTyID:
172 return true;
173 default:
174 break;
Reed Kotler2c4657d2013-05-14 02:00:24 +0000175 }
176 }
177 return false;
178}
179
180static bool needsFPReturnHelper(Function &F) {
181 Type* RetType = F.getReturnType();
182 return whichFPReturnVariant(RetType) != NoFPRet;
183}
184
Reed Kotler2500bd62013-12-18 23:57:48 +0000185static bool needsFPReturnHelper(const FunctionType &FT) {
186 Type* RetType = FT.getReturnType();
187 return whichFPReturnVariant(RetType) != NoFPRet;
188}
189
Reed Kotler2c4657d2013-05-14 02:00:24 +0000190static bool needsFPHelperFromSig(Function &F) {
191 return needsFPStubFromParams(F) || needsFPReturnHelper(F);
192}
193
194//
195// We swap between FP and Integer registers to allow Mips16 and Mips32 to
196// interoperate
197//
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000198static void swapFPIntParams(FPParamVariant PV, Module *M, InlineAsmHelper &IAH,
199 bool LE, bool ToFP) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000200 //LLVMContext &Context = M->getContext();
201 std::string MI = ToFP? "mtc1 ": "mfc1 ";
202 switch (PV) {
203 case FSig:
204 IAH.Out(MI + "$$4,$$f12");
205 break;
206 case FFSig:
207 IAH.Out(MI +"$$4,$$f12");
208 IAH.Out(MI + "$$5,$$f14");
209 break;
210 case FDSig:
211 IAH.Out(MI + "$$4,$$f12");
212 if (LE) {
213 IAH.Out(MI + "$$6,$$f14");
214 IAH.Out(MI + "$$7,$$f15");
215 } else {
216 IAH.Out(MI + "$$7,$$f14");
217 IAH.Out(MI + "$$6,$$f15");
218 }
219 break;
220 case DSig:
221 if (LE) {
222 IAH.Out(MI + "$$4,$$f12");
223 IAH.Out(MI + "$$5,$$f13");
224 } else {
225 IAH.Out(MI + "$$5,$$f12");
226 IAH.Out(MI + "$$4,$$f13");
227 }
228 break;
229 case DDSig:
230 if (LE) {
231 IAH.Out(MI + "$$4,$$f12");
232 IAH.Out(MI + "$$5,$$f13");
233 IAH.Out(MI + "$$6,$$f14");
234 IAH.Out(MI + "$$7,$$f15");
235 } else {
236 IAH.Out(MI + "$$5,$$f12");
237 IAH.Out(MI + "$$4,$$f13");
238 IAH.Out(MI + "$$7,$$f14");
239 IAH.Out(MI + "$$6,$$f15");
240 }
241 break;
242 case DFSig:
243 if (LE) {
244 IAH.Out(MI + "$$4,$$f12");
245 IAH.Out(MI + "$$5,$$f13");
246 } else {
247 IAH.Out(MI + "$$5,$$f12");
248 IAH.Out(MI + "$$4,$$f13");
249 }
250 IAH.Out(MI + "$$6,$$f14");
251 break;
252 case NoSig:
253 return;
254 }
255}
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000256
Reed Kotler2c4657d2013-05-14 02:00:24 +0000257//
258// Make sure that we know we already need a stub for this function.
259// Having called needsFPHelperFromSig
260//
Reed Kotler4cdaa7d2014-02-14 19:16:39 +0000261static void assureFPCallStub(Function &F, Module *M,
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000262 const MipsTargetMachine &TM) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000263 // for now we only need them for static relocation
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000264 if (TM.getRelocationModel() == Reloc::PIC_)
Reed Kotler2c4657d2013-05-14 02:00:24 +0000265 return;
266 LLVMContext &Context = M->getContext();
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000267 bool LE = TM.isLittleEndian();
Reed Kotler2c4657d2013-05-14 02:00:24 +0000268 std::string Name = F.getName();
269 std::string SectionName = ".mips16.call.fp." + Name;
Reed Kotler302ae6b2013-08-01 02:26:31 +0000270 std::string StubName = "__call_stub_fp_" + Name;
Reed Kotler2c4657d2013-05-14 02:00:24 +0000271 //
272 // see if we already have the stub
273 //
274 Function *FStub = M->getFunction(StubName);
275 if (FStub && !FStub->isDeclaration()) return;
276 FStub = Function::Create(F.getFunctionType(),
277 Function::InternalLinkage, StubName, M);
278 FStub->addFnAttr("mips16_fp_stub");
279 FStub->addFnAttr(llvm::Attribute::Naked);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000280 FStub->addFnAttr(llvm::Attribute::NoInline);
Reed Kotler2c4657d2013-05-14 02:00:24 +0000281 FStub->addFnAttr(llvm::Attribute::NoUnwind);
282 FStub->addFnAttr("nomips16");
283 FStub->setSection(SectionName);
284 BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
285 InlineAsmHelper IAH(Context, BB);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000286 IAH.Out(".set reorder");
Reed Kotler2c4657d2013-05-14 02:00:24 +0000287 FPReturnVariant RV = whichFPReturnVariant(FStub->getReturnType());
288 FPParamVariant PV = whichFPParamVariantNeeded(F);
289 swapFPIntParams(PV, M, IAH, LE, true);
290 if (RV != NoFPRet) {
291 IAH.Out("move $$18, $$31");
292 IAH.Out("jal " + Name);
293 } else {
294 IAH.Out("lui $$25,%hi(" + Name + ")");
295 IAH.Out("addiu $$25,$$25,%lo(" + Name + ")" );
296 }
297 switch (RV) {
298 case FRet:
299 IAH.Out("mfc1 $$2,$$f0");
300 break;
301 case DRet:
302 if (LE) {
303 IAH.Out("mfc1 $$2,$$f0");
304 IAH.Out("mfc1 $$3,$$f1");
305 } else {
306 IAH.Out("mfc1 $$3,$$f0");
307 IAH.Out("mfc1 $$2,$$f1");
308 }
309 break;
310 case CFRet:
311 if (LE) {
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000312 IAH.Out("mfc1 $$2,$$f0");
313 IAH.Out("mfc1 $$3,$$f2");
Reed Kotler2c4657d2013-05-14 02:00:24 +0000314 } else {
315 IAH.Out("mfc1 $$3,$$f0");
316 IAH.Out("mfc1 $$3,$$f2");
317 }
318 break;
319 case CDRet:
320 if (LE) {
321 IAH.Out("mfc1 $$4,$$f2");
322 IAH.Out("mfc1 $$5,$$f3");
323 IAH.Out("mfc1 $$2,$$f0");
324 IAH.Out("mfc1 $$3,$$f1");
325
326 } else {
327 IAH.Out("mfc1 $$5,$$f2");
328 IAH.Out("mfc1 $$4,$$f3");
329 IAH.Out("mfc1 $$3,$$f0");
330 IAH.Out("mfc1 $$2,$$f1");
331 }
332 break;
333 case NoFPRet:
334 break;
335 }
336 if (RV != NoFPRet)
337 IAH.Out("jr $$18");
338 else
339 IAH.Out("jr $$25");
340 new UnreachableInst(Context, BB);
341}
342
343//
Reed Kotler5fdadce2013-09-01 04:12:59 +0000344// Functions that are llvm intrinsics and don't need helpers.
Reed Kotlerd265e882013-08-11 21:30:27 +0000345//
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000346static const char *IntrinsicInline[] = {
347 "fabs", "fabsf",
348 "llvm.ceil.f32", "llvm.ceil.f64",
349 "llvm.copysign.f32", "llvm.copysign.f64",
350 "llvm.cos.f32", "llvm.cos.f64",
351 "llvm.exp.f32", "llvm.exp.f64",
352 "llvm.exp2.f32", "llvm.exp2.f64",
353 "llvm.fabs.f32", "llvm.fabs.f64",
354 "llvm.floor.f32", "llvm.floor.f64",
355 "llvm.fma.f32", "llvm.fma.f64",
356 "llvm.log.f32", "llvm.log.f64",
357 "llvm.log10.f32", "llvm.log10.f64",
358 "llvm.nearbyint.f32", "llvm.nearbyint.f64",
359 "llvm.pow.f32", "llvm.pow.f64",
360 "llvm.powi.f32", "llvm.powi.f64",
361 "llvm.rint.f32", "llvm.rint.f64",
362 "llvm.round.f32", "llvm.round.f64",
363 "llvm.sin.f32", "llvm.sin.f64",
364 "llvm.sqrt.f32", "llvm.sqrt.f64",
365 "llvm.trunc.f32", "llvm.trunc.f64",
366};
Reed Kotlerd265e882013-08-11 21:30:27 +0000367
Benjamin Kramerc9b7d472013-08-12 09:37:29 +0000368static bool isIntrinsicInline(Function *F) {
Benjamin Kramer502b9e12014-04-12 16:15:53 +0000369 return std::binary_search(std::begin(IntrinsicInline),
370 std::end(IntrinsicInline), F->getName());
Reed Kotlerd265e882013-08-11 21:30:27 +0000371}
372//
Reed Kotler783c7942013-05-10 22:25:39 +0000373// Returns of float, double and complex need to be handled with a helper
Reed Kotler515e9372013-05-16 02:17:42 +0000374// function.
Reed Kotler783c7942013-05-10 22:25:39 +0000375//
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000376static bool fixupFPReturnAndCall(Function &F, Module *M,
377 const MipsTargetMachine &TM) {
Reed Kotler783c7942013-05-10 22:25:39 +0000378 bool Modified = false;
379 LLVMContext &C = M->getContext();
380 Type *MyVoid = Type::getVoidTy(C);
381 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
382 for (BasicBlock::iterator I = BB->begin(), E = BB->end();
383 I != E; ++I) {
384 Instruction &Inst = *I;
385 if (const ReturnInst *RI = dyn_cast<ReturnInst>(I)) {
386 Value *RVal = RI->getReturnValue();
387 if (!RVal) continue;
388 //
389 // If there is a return value and it needs a helper function,
390 // figure out which one and add a call before the actual
391 // return to this helper. The purpose of the helper is to move
392 // floating point values from their soft float return mapping to
393 // where they would have been mapped to in floating point registers.
394 //
395 Type *T = RVal->getType();
396 FPReturnVariant RV = whichFPReturnVariant(T);
397 if (RV == NoFPRet) continue;
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000398 static const char* Helper[NoFPRet] = {
399 "__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",
400 "__mips16_ret_dc"
401 };
Reed Kotler783c7942013-05-10 22:25:39 +0000402 const char *Name = Helper[RV];
403 AttributeSet A;
404 Value *Params[] = {RVal};
405 Modified = true;
406 //
407 // These helper functions have a different calling ABI so
408 // this __Mips16RetHelper indicates that so that later
409 // during call setup, the proper call lowering to the helper
410 // functions will take place.
411 //
412 A = A.addAttribute(C, AttributeSet::FunctionIndex,
413 "__Mips16RetHelper");
414 A = A.addAttribute(C, AttributeSet::FunctionIndex,
415 Attribute::ReadNone);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000416 A = A.addAttribute(C, AttributeSet::FunctionIndex,
417 Attribute::NoInline);
Reid Kleckner343c3952014-11-20 23:51:47 +0000418 Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, nullptr));
Reed Kotler783c7942013-05-10 22:25:39 +0000419 CallInst::Create(F, Params, "", &Inst );
Reed Kotler2c4657d2013-05-14 02:00:24 +0000420 } else if (const CallInst *CI = dyn_cast<CallInst>(I)) {
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000421 const Value* V = CI->getCalledValue();
422 const Type* T = nullptr;
423 if (V) T = V->getType();
424 const PointerType *PFT=nullptr;
425 if (T) PFT = dyn_cast<PointerType>(T);
426 const FunctionType *FT=nullptr;
427 if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType());
428 Function *F_ = CI->getCalledFunction();
429 if (FT && needsFPReturnHelper(*FT) &&
430 !(F_ && isIntrinsicInline(F_))) {
431 Modified=true;
432 F.addFnAttr("saveS2");
433 }
434 if (F_ && !isIntrinsicInline(F_)) {
435 // pic mode calls are handled by already defined
436 // helper functions
437 if (needsFPReturnHelper(*F_)) {
Reed Kotler2500bd62013-12-18 23:57:48 +0000438 Modified=true;
439 F.addFnAttr("saveS2");
440 }
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000441 if (TM.getRelocationModel() != Reloc::PIC_ ) {
442 if (needsFPHelperFromSig(*F_)) {
443 assureFPCallStub(*F_, M, TM);
Reed Kotler2c4657d2013-05-14 02:00:24 +0000444 Modified=true;
445 }
446 }
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000447 }
Reed Kotler783c7942013-05-10 22:25:39 +0000448 }
449 }
450 return Modified;
451}
452
Reed Kotler515e9372013-05-16 02:17:42 +0000453static void createFPFnStub(Function *F, Module *M, FPParamVariant PV,
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000454 const MipsTargetMachine &TM) {
455 bool PicMode = TM.getRelocationModel() == Reloc::PIC_;
456 bool LE = TM.isLittleEndian();
Reed Kotler515e9372013-05-16 02:17:42 +0000457 LLVMContext &Context = M->getContext();
458 std::string Name = F->getName();
459 std::string SectionName = ".mips16.fn." + Name;
460 std::string StubName = "__fn_stub_" + Name;
Reed Kotlera6ce7972013-09-25 20:58:50 +0000461 std::string LocalName = "$$__fn_local_" + Name;
Reed Kotler515e9372013-05-16 02:17:42 +0000462 Function *FStub = Function::Create
463 (F->getFunctionType(),
Reed Kotler302ae6b2013-08-01 02:26:31 +0000464 Function::InternalLinkage, StubName, M);
Reed Kotler515e9372013-05-16 02:17:42 +0000465 FStub->addFnAttr("mips16_fp_stub");
466 FStub->addFnAttr(llvm::Attribute::Naked);
467 FStub->addFnAttr(llvm::Attribute::NoUnwind);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000468 FStub->addFnAttr(llvm::Attribute::NoInline);
Reed Kotler515e9372013-05-16 02:17:42 +0000469 FStub->addFnAttr("nomips16");
470 FStub->setSection(SectionName);
471 BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
472 InlineAsmHelper IAH(Context, BB);
Reed Kotler515e9372013-05-16 02:17:42 +0000473 if (PicMode) {
474 IAH.Out(".set noreorder");
Reed Kotlera6ce7972013-09-25 20:58:50 +0000475 IAH.Out(".cpload $$25");
Reed Kotler515e9372013-05-16 02:17:42 +0000476 IAH.Out(".set reorder");
477 IAH.Out(".reloc 0,R_MIPS_NONE," + Name);
478 IAH.Out("la $$25," + LocalName);
479 }
Reed Kotler78fb2912013-09-21 01:37:52 +0000480 else {
Reed Kotlera6ce7972013-09-25 20:58:50 +0000481 IAH.Out("la $$25," + Name);
Reed Kotler78fb2912013-09-21 01:37:52 +0000482 }
Reed Kotler515e9372013-05-16 02:17:42 +0000483 swapFPIntParams(PV, M, IAH, LE, false);
484 IAH.Out("jr $$25");
485 IAH.Out(LocalName + " = " + Name);
486 new UnreachableInst(FStub->getContext(), BB);
487}
488
Reed Kotlerc03807a2013-08-30 19:40:56 +0000489//
490// remove the use-soft-float attribute
491//
492static void removeUseSoftFloat(Function &F) {
493 AttributeSet A;
494 DEBUG(errs() << "removing -use-soft-float\n");
495 A = A.addAttribute(F.getContext(), AttributeSet::FunctionIndex,
496 "use-soft-float", "false");
497 F.removeAttributes(AttributeSet::FunctionIndex, A);
498 if (F.hasFnAttribute("use-soft-float")) {
499 DEBUG(errs() << "still has -use-soft-float\n");
500 }
501 F.addAttributes(AttributeSet::FunctionIndex, A);
502}
503
Reed Kotler783c7942013-05-10 22:25:39 +0000504
505//
506// This pass only makes sense when the underlying chip has floating point but
507// we are compiling as mips16.
508// For all mips16 functions (that are not stubs we have already generated), or
509// declared via attributes as nomips16, we must:
510// 1) fixup all returns of float, double, single and double complex
511// by calling a helper function before the actual return.
Reed Kotler4cdaa7d2014-02-14 19:16:39 +0000512// 2) generate helper functions (stubs) that can be called by mips32
513// functions that will move parameters passed normally passed in
514// floating point
Reed Kotler515e9372013-05-16 02:17:42 +0000515// registers the soft float equivalents.
Reed Kotler783c7942013-05-10 22:25:39 +0000516// 3) in the case of static relocation, generate helper functions so that
517// mips16 functions can call extern functions of unknown type (mips16 or
Reed Kotler515e9372013-05-16 02:17:42 +0000518// mips32).
Reed Kotler783c7942013-05-10 22:25:39 +0000519// 4) TBD. For pic, calls to extern functions of unknown type are handled by
520// predefined helper functions in libc but this work is currently done
521// during call lowering but it should be moved here in the future.
522//
523bool Mips16HardFloat::runOnModule(Module &M) {
524 DEBUG(errs() << "Run on Module Mips16HardFloat\n");
525 bool Modified = false;
526 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
Reed Kotlerc03807a2013-08-30 19:40:56 +0000527 if (F->hasFnAttribute("nomips16") &&
528 F->hasFnAttribute("use-soft-float")) {
529 removeUseSoftFloat(*F);
530 continue;
531 }
Reed Kotler783c7942013-05-10 22:25:39 +0000532 if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") ||
533 F->hasFnAttribute("nomips16")) continue;
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000534 Modified |= fixupFPReturnAndCall(*F, &M, TM);
Reed Kotler515e9372013-05-16 02:17:42 +0000535 FPParamVariant V = whichFPParamVariantNeeded(*F);
536 if (V != NoSig) {
537 Modified = true;
Eric Christopherd20ee0a2015-01-06 01:12:30 +0000538 createFPFnStub(F, &M, V, TM);
Reed Kotler515e9372013-05-16 02:17:42 +0000539 }
Reed Kotler783c7942013-05-10 22:25:39 +0000540 }
541 return Modified;
542}
543
Reed Kotler783c7942013-05-10 22:25:39 +0000544
Vasileios Kalintiris6611eb32015-03-14 09:02:23 +0000545ModulePass *llvm::createMips16HardFloatPass(MipsTargetMachine &TM) {
Reed Kotler783c7942013-05-10 22:25:39 +0000546 return new Mips16HardFloat(TM);
547}