clang  9.0.0svn
CGGPUBuiltin.cpp
Go to the documentation of this file.
1 //===------ CGGPUBuiltin.cpp - Codegen for GPU builtins -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Generates code for built-in GPU calls which are not runtime-specific.
10 // (Runtime-specific codegen lives in programming model specific files.)
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "CodeGenFunction.h"
15 #include "clang/Basic/Builtins.h"
16 #include "llvm/IR/DataLayout.h"
17 #include "llvm/IR/Instruction.h"
18 #include "llvm/Support/MathExtras.h"
19 
20 using namespace clang;
21 using namespace CodeGen;
22 
23 static llvm::Function *GetVprintfDeclaration(llvm::Module &M) {
24  llvm::Type *ArgTypes[] = {llvm::Type::getInt8PtrTy(M.getContext()),
25  llvm::Type::getInt8PtrTy(M.getContext())};
26  llvm::FunctionType *VprintfFuncType = llvm::FunctionType::get(
27  llvm::Type::getInt32Ty(M.getContext()), ArgTypes, false);
28 
29  if (auto* F = M.getFunction("vprintf")) {
30  // Our CUDA system header declares vprintf with the right signature, so
31  // nobody else should have been able to declare vprintf with a bogus
32  // signature.
33  assert(F->getFunctionType() == VprintfFuncType);
34  return F;
35  }
36 
37  // vprintf doesn't already exist; create a declaration and insert it into the
38  // module.
40  VprintfFuncType, llvm::GlobalVariable::ExternalLinkage, "vprintf", &M);
41 }
42 
43 // Transforms a call to printf into a call to the NVPTX vprintf syscall (which
44 // isn't particularly special; it's invoked just like a regular function).
45 // vprintf takes two args: A format string, and a pointer to a buffer containing
46 // the varargs.
47 //
48 // For example, the call
49 //
50 // printf("format string", arg1, arg2, arg3);
51 //
52 // is converted into something resembling
53 //
54 // struct Tmp {
55 // Arg1 a1;
56 // Arg2 a2;
57 // Arg3 a3;
58 // };
59 // char* buf = alloca(sizeof(Tmp));
60 // *(Tmp*)buf = {a1, a2, a3};
61 // vprintf("format string", buf);
62 //
63 // buf is aligned to the max of {alignof(Arg1), ...}. Furthermore, each of the
64 // args is itself aligned to its preferred alignment.
65 //
66 // Note that by the time this function runs, E's args have already undergone the
67 // standard C vararg promotion (short -> int, float -> double, etc.).
68 RValue
70  ReturnValueSlot ReturnValue) {
71  assert(getTarget().getTriple().isNVPTX());
72  assert(E->getBuiltinCallee() == Builtin::BIprintf);
73  assert(E->getNumArgs() >= 1); // printf always has at least one arg.
74 
75  const llvm::DataLayout &DL = CGM.getDataLayout();
76  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
77 
78  CallArgList Args;
79  EmitCallArgs(Args,
81  E->arguments(), E->getDirectCallee(),
82  /* ParamsToSkip = */ 0);
83 
84  // We don't know how to emit non-scalar varargs.
85  if (std::any_of(Args.begin() + 1, Args.end(), [&](const CallArg &A) {
86  return !A.getRValue(*this).isScalar();
87  })) {
88  CGM.ErrorUnsupported(E, "non-scalar arg to printf");
89  return RValue::get(llvm::ConstantInt::get(IntTy, 0));
90  }
91 
92  // Construct and fill the args buffer that we'll pass to vprintf.
93  llvm::Value *BufferPtr;
94  if (Args.size() <= 1) {
95  // If there are no args, pass a null pointer to vprintf.
96  BufferPtr = llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(Ctx));
97  } else {
99  for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I)
100  ArgTypes.push_back(Args[I].getRValue(*this).getScalarVal()->getType());
101 
102  // Using llvm::StructType is correct only because printf doesn't accept
103  // aggregates. If we had to handle aggregates here, we'd have to manually
104  // compute the offsets within the alloca -- we wouldn't be able to assume
105  // that the alignment of the llvm type was the same as the alignment of the
106  // clang type.
107  llvm::Type *AllocaTy = llvm::StructType::create(ArgTypes, "printf_args");
108  llvm::Value *Alloca = CreateTempAlloca(AllocaTy);
109 
110  for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I) {
111  llvm::Value *P = Builder.CreateStructGEP(AllocaTy, Alloca, I - 1);
112  llvm::Value *Arg = Args[I].getRValue(*this).getScalarVal();
113  Builder.CreateAlignedStore(Arg, P, DL.getPrefTypeAlignment(Arg->getType()));
114  }
115  BufferPtr = Builder.CreatePointerCast(Alloca, llvm::Type::getInt8PtrTy(Ctx));
116  }
117 
118  // Invoke vprintf and return.
119  llvm::Function* VprintfFunc = GetVprintfDeclaration(CGM.getModule());
120  return RValue::get(Builder.CreateCall(
121  VprintfFunc, {Args[0].getRValue(*this).getScalarVal(), BufferPtr}));
122 }
const llvm::DataLayout & getDataLayout() const
ReturnValueSlot - Contains the address where the return value of a function can be stored...
Definition: CGCall.h:363
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
Definition: CGBuilder.h:178
llvm::IntegerType * IntTy
int
External linkage, which indicates that the entity can be referred to from other translation units...
Definition: Linkage.h:59
llvm::LLVMContext & getLLVMContext()
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2573
StringRef P
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6766
const TargetInfo & getTarget() const
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
Definition: CGExpr.cpp:105
Represents a prototype with parameter type info, e.g.
Definition: Type.h:3697
RValue - This trivial value class is used to represent the result of an expression that is evaluated...
Definition: CGValue.h:38
void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo, llvm::iterator_range< CallExpr::const_arg_iterator > ArgRange, AbstractCallee AC=AbstractCallee(), unsigned ParamsToSkip=0, EvaluationOrder Order=EvaluationOrder::Default)
EmitCallArgs - Emit call arguments for a function.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:2565
static llvm::Function * GetVprintfDeclaration(llvm::Module &M)
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
Definition: Expr.cpp:1369
The l-value was considered opaque, so the alignment was determined from a type.
RValue EmitNVPTXDevicePrintfCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue)
arg_range arguments()
Definition: Expr.h:2623
void ErrorUnsupported(const Stmt *S, const char *Type)
Print out an error that codegen doesn&#39;t support the specified stmt yet.
Dataflow Directional Tag Classes.
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
llvm::Module & getModule() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2429
static RValue get(llvm::Value *V)
Definition: CGValue.h:85
llvm::StoreInst * CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, CharUnits Align, bool IsVolatile=false)
Definition: CGBuilder.h:114
QualType getType() const
Definition: Decl.h:647
CallArgList - Type for representing both the value and type of arguments in a call.
Definition: CGCall.h:262
Defines enum values for all the target-independent builtin functions.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr *> VL, ArrayRef< Expr *> PL, ArrayRef< Expr *> IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.