Mips16HardFloat.cpp revision 46090914b783b632618268f2a5c99aab83732688
1//===---- 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 14#define DEBUG_TYPE "mips16-hard-float" 15#include "Mips16HardFloat.h" 16#include "llvm/IR/Module.h" 17#include "llvm/Support/Debug.h" 18#include "llvm/Support/raw_ostream.h" 19#include <string> 20 21// 22// Return types that matter for hard float are: 23// float, double, complex float, and complex double 24// 25enum FPReturnVariant { 26 FRet, DRet, CFRet, CDRet, NoFPRet 27}; 28 29// 30// Determine which FP return type this function has 31// 32static FPReturnVariant whichFPReturnVariant(Type *T) { 33 switch (T->getTypeID()) { 34 case Type::FloatTyID: 35 return FRet; 36 case Type::DoubleTyID: 37 return DRet; 38 case Type::StructTyID: 39 if (T->getStructNumElements() != 2) 40 break; 41 if ((T->getContainedType(0)->isFloatTy()) && 42 (T->getContainedType(1)->isFloatTy())) 43 return CFRet; 44 if ((T->getContainedType(0)->isDoubleTy()) && 45 (T->getContainedType(1)->isDoubleTy())) 46 return CDRet; 47 break; 48 default: 49 break; 50 } 51 return NoFPRet; 52} 53 54// 55// Returns of float, double and complex need to be handled with a helper 56// function. The "AndCal" part is coming in a later patch. 57// 58static bool fixupFPReturnAndCall 59 (Function &F, Module *M, const MipsSubtarget &Subtarget) { 60 bool Modified = false; 61 LLVMContext &C = M->getContext(); 62 Type *MyVoid = Type::getVoidTy(C); 63 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) 64 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); 65 I != E; ++I) { 66 Instruction &Inst = *I; 67 if (const ReturnInst *RI = dyn_cast<ReturnInst>(I)) { 68 Value *RVal = RI->getReturnValue(); 69 if (!RVal) continue; 70 // 71 // If there is a return value and it needs a helper function, 72 // figure out which one and add a call before the actual 73 // return to this helper. The purpose of the helper is to move 74 // floating point values from their soft float return mapping to 75 // where they would have been mapped to in floating point registers. 76 // 77 Type *T = RVal->getType(); 78 FPReturnVariant RV = whichFPReturnVariant(T); 79 if (RV == NoFPRet) continue; 80 static const char* Helper[NoFPRet] = 81 {"__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc", 82 "__mips16_ret_dc"}; 83 const char *Name = Helper[RV]; 84 AttributeSet A; 85 Value *Params[] = {RVal}; 86 Modified = true; 87 // 88 // These helper functions have a different calling ABI so 89 // this __Mips16RetHelper indicates that so that later 90 // during call setup, the proper call lowering to the helper 91 // functions will take place. 92 // 93 A = A.addAttribute(C, AttributeSet::FunctionIndex, 94 "__Mips16RetHelper"); 95 A = A.addAttribute(C, AttributeSet::FunctionIndex, 96 Attribute::ReadNone); 97 Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, NULL)); 98 CallInst::Create(F, Params, "", &Inst ); 99 } 100 } 101 return Modified; 102} 103 104namespace llvm { 105 106// 107// This pass only makes sense when the underlying chip has floating point but 108// we are compiling as mips16. 109// For all mips16 functions (that are not stubs we have already generated), or 110// declared via attributes as nomips16, we must: 111// 1) fixup all returns of float, double, single and double complex 112// by calling a helper function before the actual return. 113// 2) generate helper functions (stubs) that can be called by mips32 functions 114// that will move parameters passed normally passed in floating point 115// registers the soft float equivalents. (Coming in a later patch). 116// 3) in the case of static relocation, generate helper functions so that 117// mips16 functions can call extern functions of unknown type (mips16 or 118// mips32). (Coming in a later patch). 119// 4) TBD. For pic, calls to extern functions of unknown type are handled by 120// predefined helper functions in libc but this work is currently done 121// during call lowering but it should be moved here in the future. 122// 123bool Mips16HardFloat::runOnModule(Module &M) { 124 DEBUG(errs() << "Run on Module Mips16HardFloat\n"); 125 bool Modified = false; 126 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { 127 if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") || 128 F->hasFnAttribute("nomips16")) continue; 129 Modified |= fixupFPReturnAndCall(*F, &M, Subtarget); 130 } 131 return Modified; 132} 133 134char Mips16HardFloat::ID = 0; 135 136} 137 138ModulePass *llvm::createMips16HardFloat(MipsTargetMachine &TM) { 139 return new Mips16HardFloat(TM); 140} 141 142