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