diff options
| author | Alon Zakai <alonzakai@gmail.com> | 2013-12-08 21:21:19 -0500 |
|---|---|---|
| committer | Alon Zakai <alonzakai@gmail.com> | 2013-12-08 21:21:19 -0500 |
| commit | 157acdad8b75baa91beab3ac8a8ee336453bf818 (patch) | |
| tree | b64c5961f2026242ed64252fca05b60559860e25 /lib/Transforms | |
| parent | a07a863344f8fd1124a4336251bfe2d581abcfdb (diff) | |
wip call legalizing
Diffstat (limited to 'lib/Transforms')
| -rw-r--r-- | lib/Transforms/NaCl/ExpandI64.cpp | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/lib/Transforms/NaCl/ExpandI64.cpp b/lib/Transforms/NaCl/ExpandI64.cpp index 3b74f9a048..6b3762b298 100644 --- a/lib/Transforms/NaCl/ExpandI64.cpp +++ b/lib/Transforms/NaCl/ExpandI64.cpp @@ -73,6 +73,9 @@ namespace { class ExpandI64 : public ModulePass { SplitsMap Splits; // old i64 value to new insts + // If the function has an illegal return or argument, create a legal version + void ensureLegalFunc(Function *F); + // splits a 64-bit instruction into 32-bit chunks. We do // not yet have the values yet, as they depend on other // splits, so store the parts in Splits, for FinalizeInst. @@ -110,8 +113,48 @@ INITIALIZE_PASS(ExpandI64, "expand-i64", "Expand and lower i64 operations into 32-bit chunks", false, false) -//static void ExpandI64Func(Function *Func) { -//} +// Utilities + +static bool isIllegal(Type *T) { + return T->isIntegerTy() && T->getIntegerBitWidth() == 64; +} + +static FunctionType *getLegalizedFunctionType(FunctionType *FT) { + SmallVector<Type*, 0> ArgTypes; // XXX + int Num = FT->getNumParams(); + for (int i = 0; i < Num; i++) { + Type *T = FT->getParamType(i); + if (!isIllegal(T)) { + ArgTypes.push_back(T); + } else { + Type *i32 = Type::getInt32Ty(FT->getContext()); + ArgTypes.push_back(i32); + ArgTypes.push_back(i32); + } + } + Type *RT = FT->getReturnType(); + Type *NewRT; + if (!isIllegal(RT)) { + NewRT = RT; + } else { + NewRT = Type::getInt32Ty(FT->getContext()); + } + return FunctionType::get(NewRT, ArgTypes, false); +} + +// Implementation of ExpandI64 + +void ExpandI64::ensureLegalFunc(Function *F) { + FunctionType *FT = F->getFunctionType(); + int Num = FT->getNumParams(); + for (int i = -1; i < Num; i++) { + Type *T = i == -1 ? FT->getReturnType() : FT->getParamType(i); + if (isIllegal(T)) { + RecreateFunction(F, getLegalizedFunctionType(FT)); + break; + } + } +} void ExpandI64::splitInst(Instruction *I, DataLayout& DL) { Type *i32 = Type::getInt32Ty(I->getContext()); @@ -319,6 +362,38 @@ void ExpandI64::splitInst(Instruction *I, DataLayout& DL) { Split.ToFix.push_back(H); Split.LowHigh.High = H; break; } + case Instruction::Call: { + CallInst *CI = dyn_cast<CallInst>(I); + Function *F = CI->getCalledFunction(); + dumpIR(CI); + dumpIR(F); + assert(F); // TODO: handle indirect i64-returning functions, varargs i64 functions, etc. + FunctionType *FT = dyn_cast<FunctionType>(F->getType()); + + // create a call with space for legal args + SmallVector<Value *, 0> Args; // XXX + int Num = FT->getNumParams(); + for (int i = 0; i < Num; i++) { + Type *T = FT->getParamType(i); + if (!isIllegal(T)) { + Args.push_back(CI->getArgOperand(i)); + } else { + Args.push_back(Zero); // will be fixed + Args.push_back(Zero); + } + } + Instruction *L = CopyDebug(CallInst::Create(F, Args, "", I), I); + Instruction *H = NULL; + // legalize return value as well, if necessary + if (isIllegal(I->getType())) { + H = CopyDebug(CallInst::Create(GetHigh, "", I), I); + } + + SplitInfo &Split = Splits[I]; + Split.ToFix.push_back(L); Split.LowHigh.Low = L; + Split.ToFix.push_back(H); Split.LowHigh.High = H; + break; + } default: { dumpIR(I); assert(0 && "some i64 thing we can't legalize yet"); @@ -495,6 +570,12 @@ bool ExpandI64::runOnModule(Module &M) { bool Changed = false; DataLayout DL(&M); + // pre pass - legalize functions + for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) { + Function *Func = Iter++; + ensureLegalFunc(Func); + } + // first pass - split for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) { Function *Func = Iter++; @@ -509,7 +590,7 @@ bool ExpandI64::runOnModule(Module &M) { int Num = I->getNumOperands(); for (int i = -1; i < Num; i++) { // -1 is the type of I itself Type *T = i == -1 ? I->getType() : I->getOperand(i)->getType(); - if (T->isIntegerTy() && T->getIntegerBitWidth() == 64) { + if (isIllegal(T)) { Changed = true; //dump("split"); dumpIR(I); splitInst(I, DL); @@ -538,7 +619,7 @@ bool ExpandI64::runOnModule(Module &M) { for (int i = 0; i < Num; i++) { // -1 is the type of I itself Value *V = I->first->getOperand(i); Type *T = V->getType(); - if (T->isIntegerTy() && T->getIntegerBitWidth() == 64) { + if (isIllegal(T)) { I->first->setOperand(i, Zero); } } |
