142b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao/*
242b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * Copyright 2012, The Android Open Source Project
342b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao *
442b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License");
542b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * you may not use this file except in compliance with the License.
642b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * You may obtain a copy of the License at
742b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao *
842b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao *     http://www.apache.org/licenses/LICENSE-2.0
942b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao *
1042b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * Unless required by applicable law or agreed to in writing, software
1142b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS,
1242b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1342b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * See the License for the specific language governing permissions and
1442b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao * limitations under the License.
1542b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao */
1642b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
1742b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/ADT/Triple.h>
1842b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/DerivedTypes.h>
1942b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/Function.h>
2042b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/Instructions.h>
2142b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/IRBuilder.h>
2242b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/Module.h>
2342b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/Pass.h>
2442b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/Type.h>
2542b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include <llvm/Target/TargetData.h>
2642b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
2742b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include "bcc/AndroidBitcode/ABCExpandVAArgPass.h"
2842b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
2942b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao#include "X86/X86ABCCompilerDriver.h"
3042b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
3142b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liaonamespace {
3242b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
3342b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liaoclass X86ABCExpandVAArg : public bcc::ABCExpandVAArgPass {
3442b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liaopublic:
3542b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao  virtual const char *getPassName() const {
3642b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    return "X86 LLVM va_arg Instruction Expansion Pass";
3742b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao  }
3842b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
3942b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liaoprivate:
4042b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao  // Derivative work from external/clang/lib/CodeGen/TargetInfo.cpp.
4142b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao  virtual llvm::Value *expandVAArg(llvm::Instruction *pInst) {
4242b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Type *pty = pInst->getType();
4342b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Type *ty = pty->getContainedType(0);
4442b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Value *va_list_addr = pInst->getOperand(0);
4542b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::IRBuilder<> builder(pInst);
4642b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    const llvm::TargetData *td = getAnalysisIfAvailable<llvm::TargetData>();
4742b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
4842b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Type *bp = llvm::Type::getInt8PtrTy(*mContext);
4942b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Type *bpp = bp->getPointerTo(0);
5042b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Value *va_list_addr_bpp = builder.CreateBitCast(va_list_addr,
5142b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao                                                          bpp, "ap");
5242b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Value *addr = builder.CreateLoad(va_list_addr_bpp, "ap.cur");
5342b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
5442b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Value *addr_typed = builder.CreateBitCast(addr, pty);
5542b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
5642b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    // X86-32 stack type alignment is always 4.
5742b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    uint64_t offset = llvm::RoundUpToAlignment(td->getTypeSizeInBits(ty)/8, 4);
5842b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    llvm::Value *next_addr = builder.CreateGEP(addr,
5942b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao      llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext), offset),
6042b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao      "ap.next");
6142b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    builder.CreateStore(next_addr, va_list_addr_bpp);
6242b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
6342b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao    return addr_typed;
6442b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao  }
6542b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
6642b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao}; // end X86ABCExpandVAArg
6742b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
6842b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao} // end anonymous namespace
6942b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
7042b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liaonamespace bcc {
7142b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
7242b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei LiaoABCExpandVAArgPass *X86ABCCompilerDriver::createExpandVAArgPass() const {
7342b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao  return new X86ABCExpandVAArg();
7442b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao}
7542b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao
7642b88c3b3cdadf6fcd367ee2bc620c0c94bbfe1bShih-wei Liao} // end namespace bcc
77