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 31namespace { 32 33class X86ABCExpandVAArg : public bcc::ABCExpandVAArgPass { 34public: 35 virtual const char *getPassName() const { 36 return "X86 LLVM va_arg Instruction Expansion Pass"; 37 } 38 39private: 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 70namespace bcc { 71 72ABCExpandVAArgPass *X86ABCCompilerDriver::createExpandVAArgPass() const { 73 return new X86ABCExpandVAArg(); 74} 75 76} // end namespace bcc 77