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