//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Builtin calls as LLVM code.
//
//===----------------------------------------------------------------------===//
#include "TargetInfo.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/Intrinsics.h"
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
using namespace llvm;
static void EmitMemoryBarrier(CodeGenFunction &CGF,
bool LoadLoad, bool LoadStore,
bool StoreLoad, bool StoreStore,
bool Device) {
Value *True = llvm::ConstantInt::getTrue(CGF.getLLVMContext());
Value *False = llvm::ConstantInt::getFalse(CGF.getLLVMContext());
Value *C[5] = { LoadLoad ? True : False,
LoadStore ? True : False,
StoreLoad ? True : False,
StoreStore ? True : False,
Device ? True : False };
CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::memory_barrier),
C, C + 5);
}
// The atomic builtins are also full memory barriers. This is a utility for
// wrapping a call to the builtins with memory barriers.
static Value *EmitCallWithBarrier(CodeGenFunction &CGF, Value *Fn,
Value **ArgBegin, Value **ArgEnd) {
// FIXME: We need a target hook for whether this applies to device memory or
// not.
bool Device = true;
// Create barriers both before and after the call.
EmitMemoryBarrier(CGF, true, true, true, true, Device);
Value *Result = CGF.Builder.CreateCall(Fn, ArgBegin, ArgEnd);
EmitMemoryBarrier(CGF, true, true, true, true, Device);
return Result;
}
/// Utility to insert an atomic instruction based on Instrinsic::ID
/// and the expression node.
static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
Intrinsic::ID Id, const CallExpr *E) {
Value *Args[2] = { CGF.EmitScalarExpr(E->getArg(0)),
CGF.EmitScalarExpr(E->getArg(1)) };
const llvm::Type *ResType[2];
ResType[0] = CGF.ConvertType(E->getType());
ResType[1] = CGF.ConvertType(E->getArg(0)->getType());
Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2);
return RValue::get(EmitCallWithBarrier(CGF, AtomF, Args, Args + 2));
}
/// Utility to insert an atomic instruction based Instrinsic::ID and
// the expression node, where the return value is the result of the
// operation.
static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF,
Intrinsic::ID Id, const CallExpr *E,
Instruction::BinaryOps Op) {
const llvm::Type *ResType[2];
ResType[0] = CGF.ConvertType(E->getType());
ResType[1] = CGF.ConvertType(E->getArg(0)->getType());
Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2);
Value *Args[2] = { CGF.EmitScalarExpr(E->getArg(0)),
CGF.EmitScalarExpr(E->getArg(1)) };
Value *Result = EmitCallWithBarrier(CGF, AtomF, Args, Args + 2);
return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Args[1]));
}
static llvm::ConstantInt *getInt32(llvm::LLVMContext &Context, int32_t Value) {
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), Value);
}
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E) {
// See if we can constant fold this builtin. If so, don't emit it at all.
Expr::EvalResult