slang_rs_backend.cpp revision eca0534a31b6185d6ab758f5e97acd7a4cb21e8e
1/*
2 * Copyright 2010-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 "slang_rs_backend.h"
18
19#include <string>
20#include <vector>
21
22#include "clang/AST/ASTContext.h"
23#include "clang/Frontend/CodeGenOptions.h"
24
25#include "llvm/ADT/Twine.h"
26#include "llvm/ADT/StringExtras.h"
27
28#include "llvm/IR/Constant.h"
29#include "llvm/IR/Constants.h"
30#include "llvm/IR/DerivedTypes.h"
31#include "llvm/IR/Function.h"
32#include "llvm/IR/IRBuilder.h"
33#include "llvm/IR/Metadata.h"
34#include "llvm/IR/Module.h"
35
36#include "llvm/IR/DebugLoc.h"
37
38#include "slang_assert.h"
39#include "slang_rs.h"
40#include "slang_rs_context.h"
41#include "slang_rs_export_foreach.h"
42#include "slang_rs_export_func.h"
43#include "slang_rs_export_type.h"
44#include "slang_rs_export_var.h"
45#include "slang_rs_metadata.h"
46
47namespace slang {
48
49RSBackend::RSBackend(RSContext *Context,
50                     clang::DiagnosticsEngine *DiagEngine,
51                     const clang::CodeGenOptions &CodeGenOpts,
52                     const clang::TargetOptions &TargetOpts,
53                     PragmaList *Pragmas,
54                     llvm::raw_ostream *OS,
55                     Slang::OutputType OT,
56                     clang::SourceManager &SourceMgr,
57                     bool AllowRSPrefix,
58                     bool IsFilterscript)
59  : Backend(DiagEngine, CodeGenOpts, TargetOpts, Pragmas, OS, OT),
60    mContext(Context),
61    mSourceMgr(SourceMgr),
62    mAllowRSPrefix(AllowRSPrefix),
63    mIsFilterscript(IsFilterscript),
64    mExportVarMetadata(NULL),
65    mExportFuncMetadata(NULL),
66    mExportForEachNameMetadata(NULL),
67    mExportForEachSignatureMetadata(NULL),
68    mExportTypeMetadata(NULL),
69    mRSObjectSlotsMetadata(NULL),
70    mRefCount(mContext->getASTContext()),
71    mASTChecker(Context, Context->getTargetAPI(), IsFilterscript) {
72}
73
74// 1) Add zero initialization of local RS object types
75void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
76  if (FD &&
77      FD->hasBody() &&
78      !SlangRS::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
79    mRefCount.Init();
80    mRefCount.Visit(FD->getBody());
81  }
82  return;
83}
84
85bool RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
86  // Disallow user-defined functions with prefix "rs"
87  if (!mAllowRSPrefix) {
88    // Iterate all function declarations in the program.
89    for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
90         I != E; I++) {
91      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
92      if (FD == NULL)
93        continue;
94      if (!FD->getName().startswith("rs"))  // Check prefix
95        continue;
96      if (!SlangRS::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
97        mContext->ReportError(FD->getLocation(),
98                              "invalid function name prefix, "
99                              "\"rs\" is reserved: '%0'")
100            << FD->getName();
101    }
102  }
103
104  // Process any non-static function declarations
105  for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
106    clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
107    if (FD && FD->isGlobal()) {
108      // Check that we don't have any array parameters being misintrepeted as
109      // kernel pointers due to the C type system's array to pointer decay.
110      size_t numParams = FD->getNumParams();
111      for (size_t i = 0; i < numParams; i++) {
112        const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
113        clang::QualType QT = PVD->getOriginalType();
114        if (QT->isArrayType()) {
115          mContext->ReportError(
116              PVD->getTypeSpecStartLoc(),
117              "exported function parameters may not have array type: %0")
118              << QT;
119        }
120      }
121      AnnotateFunction(FD);
122    }
123  }
124
125  return Backend::HandleTopLevelDecl(D);
126}
127
128
129void RSBackend::HandleTranslationUnitPre(clang::ASTContext &C) {
130  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
131
132  // If we have an invalid RS/FS AST, don't check further.
133  if (!mASTChecker.Validate()) {
134    return;
135  }
136
137  if (mIsFilterscript) {
138    mContext->addPragma("rs_fp_relaxed", "");
139  }
140
141  int version = mContext->getVersion();
142  if (version == 0) {
143    // Not setting a version is an error
144    mDiagEngine.Report(
145        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
146        mDiagEngine.getCustomDiagID(
147            clang::DiagnosticsEngine::Error,
148            "missing pragma for version in source file"));
149  } else {
150    slangAssert(version == 1);
151  }
152
153  if (mContext->getReflectJavaPackageName().empty()) {
154    mDiagEngine.Report(
155        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
156        mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
157                                    "missing \"#pragma rs "
158                                    "java_package_name(com.foo.bar)\" "
159                                    "in source file"));
160    return;
161  }
162
163  // Create a static global destructor if necessary (to handle RS object
164  // runtime cleanup).
165  clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
166  if (FD) {
167    HandleTopLevelDecl(clang::DeclGroupRef(FD));
168  }
169
170  // Process any static function declarations
171  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
172          E = TUDecl->decls_end(); I != E; I++) {
173    if ((I->getKind() >= clang::Decl::firstFunction) &&
174        (I->getKind() <= clang::Decl::lastFunction)) {
175      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
176      if (FD && !FD->isGlobal()) {
177        AnnotateFunction(FD);
178      }
179    }
180  }
181
182  return;
183}
184
185///////////////////////////////////////////////////////////////////////////////
186void RSBackend::dumpExportVarInfo(llvm::Module *M) {
187  int slotCount = 0;
188  if (mExportVarMetadata == NULL)
189    mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
190
191  llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
192
193  // We emit slot information (#rs_object_slots) for any reference counted
194  // RS type or pointer (which can also be bound).
195
196  for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
197          E = mContext->export_vars_end();
198       I != E;
199       I++) {
200    const RSExportVar *EV = *I;
201    const RSExportType *ET = EV->getType();
202    bool countsAsRSObject = false;
203
204    // Variable name
205    ExportVarInfo.push_back(
206        llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
207
208    // Type name
209    switch (ET->getClass()) {
210      case RSExportType::ExportClassPrimitive: {
211        const RSExportPrimitiveType *PT =
212            static_cast<const RSExportPrimitiveType*>(ET);
213        ExportVarInfo.push_back(
214            llvm::MDString::get(
215              mLLVMContext, llvm::utostr_32(PT->getType())));
216        if (PT->isRSObjectType()) {
217          countsAsRSObject = true;
218        }
219        break;
220      }
221      case RSExportType::ExportClassPointer: {
222        ExportVarInfo.push_back(
223            llvm::MDString::get(
224              mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
225                ->getPointeeType()->getName()).c_str()));
226        break;
227      }
228      case RSExportType::ExportClassMatrix: {
229        ExportVarInfo.push_back(
230            llvm::MDString::get(
231              mLLVMContext, llvm::utostr_32(
232                  /* TODO Strange value.  This pushes just a number, quite
233                   * different than the other cases.  What is this used for?
234                   * These are the metadata values that some partner drivers
235                   * want to reference (for TBAA, etc.). We may want to look
236                   * at whether these provide any reasonable value (or have
237                   * distinct enough values to actually depend on).
238                   */
239                DataTypeRSMatrix2x2 +
240                static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
241        break;
242      }
243      case RSExportType::ExportClassVector:
244      case RSExportType::ExportClassConstantArray:
245      case RSExportType::ExportClassRecord: {
246        ExportVarInfo.push_back(
247            llvm::MDString::get(mLLVMContext,
248              EV->getType()->getName().c_str()));
249        break;
250      }
251    }
252
253    mExportVarMetadata->addOperand(
254        llvm::MDNode::get(mLLVMContext, ExportVarInfo));
255    ExportVarInfo.clear();
256
257    if (mRSObjectSlotsMetadata == NULL) {
258      mRSObjectSlotsMetadata =
259          M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
260    }
261
262    if (countsAsRSObject) {
263      mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
264          llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
265    }
266
267    slotCount++;
268  }
269}
270
271void RSBackend::dumpExportFunctionInfo(llvm::Module *M) {
272  if (mExportFuncMetadata == NULL)
273    mExportFuncMetadata =
274        M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
275
276  llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
277
278  for (RSContext::const_export_func_iterator
279          I = mContext->export_funcs_begin(),
280          E = mContext->export_funcs_end();
281       I != E;
282       I++) {
283    const RSExportFunc *EF = *I;
284
285    // Function name
286    if (!EF->hasParam()) {
287      ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
288                                                   EF->getName().c_str()));
289    } else {
290      llvm::Function *F = M->getFunction(EF->getName());
291      llvm::Function *HelperFunction;
292      const std::string HelperFunctionName(".helper_" + EF->getName());
293
294      slangAssert(F && "Function marked as exported disappeared in Bitcode");
295
296      // Create helper function
297      {
298        llvm::StructType *HelperFunctionParameterTy = NULL;
299
300        if (!F->getArgumentList().empty()) {
301          std::vector<llvm::Type*> HelperFunctionParameterTys;
302          for (llvm::Function::arg_iterator AI = F->arg_begin(),
303               AE = F->arg_end(); AI != AE; AI++)
304            HelperFunctionParameterTys.push_back(AI->getType());
305
306          HelperFunctionParameterTy =
307              llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
308        }
309
310        if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
311          fprintf(stderr, "Failed to export function %s: parameter type "
312                          "mismatch during creation of helper function.\n",
313                  EF->getName().c_str());
314
315          const RSExportRecordType *Expected = EF->getParamPacketType();
316          if (Expected) {
317            fprintf(stderr, "Expected:\n");
318            Expected->getLLVMType()->dump();
319          }
320          if (HelperFunctionParameterTy) {
321            fprintf(stderr, "Got:\n");
322            HelperFunctionParameterTy->dump();
323          }
324        }
325
326        std::vector<llvm::Type*> Params;
327        if (HelperFunctionParameterTy) {
328          llvm::PointerType *HelperFunctionParameterTyP =
329              llvm::PointerType::getUnqual(HelperFunctionParameterTy);
330          Params.push_back(HelperFunctionParameterTyP);
331        }
332
333        llvm::FunctionType * HelperFunctionType =
334            llvm::FunctionType::get(F->getReturnType(),
335                                    Params,
336                                    /* IsVarArgs = */false);
337
338        HelperFunction =
339            llvm::Function::Create(HelperFunctionType,
340                                   llvm::GlobalValue::ExternalLinkage,
341                                   HelperFunctionName,
342                                   M);
343
344        HelperFunction->addFnAttr(llvm::Attribute::NoInline);
345        HelperFunction->setCallingConv(F->getCallingConv());
346
347        // Create helper function body
348        {
349          llvm::Argument *HelperFunctionParameter =
350              &(*HelperFunction->arg_begin());
351          llvm::BasicBlock *BB =
352              llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
353          llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
354          llvm::SmallVector<llvm::Value*, 6> Params;
355          llvm::Value *Idx[2];
356
357          Idx[0] =
358              llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
359
360          // getelementptr and load instruction for all elements in
361          // parameter .p
362          for (size_t i = 0; i < EF->getNumParameters(); i++) {
363            // getelementptr
364            Idx[1] = llvm::ConstantInt::get(
365              llvm::Type::getInt32Ty(mLLVMContext), i);
366
367            llvm::Value *Ptr =
368              IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
369
370            // load
371            llvm::Value *V = IB->CreateLoad(Ptr);
372            Params.push_back(V);
373          }
374
375          // Call and pass the all elements as parameter to F
376          llvm::CallInst *CI = IB->CreateCall(F, Params);
377
378          CI->setCallingConv(F->getCallingConv());
379
380          if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
381            IB->CreateRetVoid();
382          else
383            IB->CreateRet(CI);
384
385          delete IB;
386        }
387      }
388
389      ExportFuncInfo.push_back(
390          llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
391    }
392
393    mExportFuncMetadata->addOperand(
394        llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
395    ExportFuncInfo.clear();
396  }
397}
398
399void RSBackend::dumpExportForEachInfo(llvm::Module *M) {
400  if (mExportForEachNameMetadata == NULL) {
401    mExportForEachNameMetadata =
402        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
403  }
404  if (mExportForEachSignatureMetadata == NULL) {
405    mExportForEachSignatureMetadata =
406        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
407  }
408
409  llvm::SmallVector<llvm::Value*, 1> ExportForEachName;
410  llvm::SmallVector<llvm::Value*, 1> ExportForEachInfo;
411
412  for (RSContext::const_export_foreach_iterator
413          I = mContext->export_foreach_begin(),
414          E = mContext->export_foreach_end();
415       I != E;
416       I++) {
417    const RSExportForEach *EFE = *I;
418
419    ExportForEachName.push_back(
420        llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
421
422    mExportForEachNameMetadata->addOperand(
423        llvm::MDNode::get(mLLVMContext, ExportForEachName));
424    ExportForEachName.clear();
425
426    ExportForEachInfo.push_back(
427        llvm::MDString::get(mLLVMContext,
428                            llvm::utostr_32(EFE->getSignatureMetadata())));
429
430    mExportForEachSignatureMetadata->addOperand(
431        llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
432    ExportForEachInfo.clear();
433  }
434}
435
436void RSBackend::dumpExportTypeInfo(llvm::Module *M) {
437  llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
438
439  for (RSContext::const_export_type_iterator
440          I = mContext->export_types_begin(),
441          E = mContext->export_types_end();
442       I != E;
443       I++) {
444    // First, dump type name list to export
445    const RSExportType *ET = I->getValue();
446
447    ExportTypeInfo.clear();
448    // Type name
449    ExportTypeInfo.push_back(
450        llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
451
452    if (ET->getClass() == RSExportType::ExportClassRecord) {
453      const RSExportRecordType *ERT =
454          static_cast<const RSExportRecordType*>(ET);
455
456      if (mExportTypeMetadata == NULL)
457        mExportTypeMetadata =
458            M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
459
460      mExportTypeMetadata->addOperand(
461          llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
462
463      // Now, export struct field information to %[struct name]
464      std::string StructInfoMetadataName("%");
465      StructInfoMetadataName.append(ET->getName());
466      llvm::NamedMDNode *StructInfoMetadata =
467          M->getOrInsertNamedMetadata(StructInfoMetadataName);
468      llvm::SmallVector<llvm::Value*, 3> FieldInfo;
469
470      slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
471                  "Metadata with same name was created before");
472      for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
473              FE = ERT->fields_end();
474           FI != FE;
475           FI++) {
476        const RSExportRecordType::Field *F = *FI;
477
478        // 1. field name
479        FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
480                                                F->getName().c_str()));
481
482        // 2. field type name
483        FieldInfo.push_back(
484            llvm::MDString::get(mLLVMContext,
485                                F->getType()->getName().c_str()));
486
487        StructInfoMetadata->addOperand(
488            llvm::MDNode::get(mLLVMContext, FieldInfo));
489        FieldInfo.clear();
490      }
491    }   // ET->getClass() == RSExportType::ExportClassRecord
492  }
493}
494
495void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
496  if (!mContext->processExport()) {
497    return;
498  }
499
500  if (mContext->hasExportVar())
501    dumpExportVarInfo(M);
502
503  if (mContext->hasExportFunc())
504    dumpExportFunctionInfo(M);
505
506  if (mContext->hasExportForEach())
507    dumpExportForEachInfo(M);
508
509  if (mContext->hasExportType())
510    dumpExportTypeInfo(M);
511
512  return;
513}
514
515RSBackend::~RSBackend() {
516  return;
517}
518
519}  // namespace slang
520