1 /* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <llvm/ADT/Triple.h> 18 #include <llvm/DerivedTypes.h> 19 #include <llvm/Function.h> 20 #include <llvm/Instructions.h> 21 #include <llvm/IRBuilder.h> 22 #include <llvm/Module.h> 23 #include <llvm/Pass.h> 24 #include <llvm/Type.h> 25 #include <llvm/Target/TargetData.h> 26 27 #include "bcc/AndroidBitcode/ABCExpandVAArgPass.h" 28 29 #include "X86/X86ABCCompilerDriver.h" 30 31 namespace { 32 33 class X86ABCExpandVAArg : public bcc::ABCExpandVAArgPass { 34 public: 35 virtual const char *getPassName() const { 36 return "X86 LLVM va_arg Instruction Expansion Pass"; 37 } 38 39 private: 40 // Derivative work from external/clang/lib/CodeGen/TargetInfo.cpp. 41 virtual llvm::Value *expandVAArg(llvm::Instruction *pInst) { 42 llvm::Type *pty = pInst->getType(); 43 llvm::Type *ty = pty->getContainedType(0); 44 llvm::Value *va_list_addr = pInst->getOperand(0); 45 llvm::IRBuilder<> builder(pInst); 46 const llvm::TargetData *td = getAnalysisIfAvailable<llvm::TargetData>(); 47 48 llvm::Type *bp = llvm::Type::getInt8PtrTy(*mContext); 49 llvm::Type *bpp = bp->getPointerTo(0); 50 llvm::Value *va_list_addr_bpp = builder.CreateBitCast(va_list_addr, 51 bpp, "ap"); 52 llvm::Value *addr = builder.CreateLoad(va_list_addr_bpp, "ap.cur"); 53 54 llvm::Value *addr_typed = builder.CreateBitCast(addr, pty); 55 56 // X86-32 stack type alignment is always 4. 57 uint64_t offset = llvm::RoundUpToAlignment(td->getTypeSizeInBits(ty)/8, 4); 58 llvm::Value *next_addr = builder.CreateGEP(addr, 59 llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext), offset), 60 "ap.next"); 61 builder.CreateStore(next_addr, va_list_addr_bpp); 62 63 return addr_typed; 64 } 65 66 }; // end X86ABCExpandVAArg 67 68 } // end anonymous namespace 69 70 namespace bcc { 71 72 ABCExpandVAArgPass *X86ABCCompilerDriver::createExpandVAArgPass() const { 73 return new X86ABCExpandVAArg(); 74 } 75 76 } // end namespace bcc 77