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