|
Intel SPMD Program Compiler
1.3.0
|
00001 /* 00002 Copyright (c) 2010-2012, Intel Corporation 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions are 00007 met: 00008 00009 * Redistributions of source code must retain the above copyright 00010 notice, this list of conditions and the following disclaimer. 00011 00012 * Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in the 00014 documentation and/or other materials provided with the distribution. 00015 00016 * Neither the name of Intel Corporation nor the names of its 00017 contributors may be used to endorse or promote products derived from 00018 this software without specific prior written permission. 00019 00020 00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00022 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00023 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00024 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00025 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00027 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 */ 00033 00034 /** @file module.cpp 00035 @brief Impementation of the Module class, which collects the result of compiling 00036 a source file and then generates output (object files, etc.) 00037 */ 00038 00039 #include "module.h" 00040 #include "util.h" 00041 #include "ctx.h" 00042 #include "func.h" 00043 #include "builtins.h" 00044 #include "type.h" 00045 #include "expr.h" 00046 #include "sym.h" 00047 #include "stmt.h" 00048 #include "opt.h" 00049 #include "llvmutil.h" 00050 00051 #include <stdio.h> 00052 #include <stdarg.h> 00053 #include <ctype.h> 00054 #include <sys/types.h> 00055 #include <sys/stat.h> 00056 #include <fcntl.h> 00057 #include <algorithm> 00058 #include <set> 00059 #include <sstream> 00060 #include <iostream> 00061 #ifdef ISPC_IS_WINDOWS 00062 #include <windows.h> 00063 #include <io.h> 00064 #define strcasecmp stricmp 00065 #endif 00066 00067 #include <llvm/LLVMContext.h> 00068 #include <llvm/Module.h> 00069 #include <llvm/Type.h> 00070 #include <llvm/DerivedTypes.h> 00071 #include <llvm/Instructions.h> 00072 #include <llvm/Intrinsics.h> 00073 #include <llvm/PassManager.h> 00074 #include <llvm/PassRegistry.h> 00075 #include <llvm/Transforms/IPO.h> 00076 #include <llvm/Support/FormattedStream.h> 00077 #include <llvm/Support/FileUtilities.h> 00078 #include <llvm/Target/TargetMachine.h> 00079 #include <llvm/Target/TargetOptions.h> 00080 #include <llvm/Target/TargetData.h> 00081 #include <llvm/Analysis/Verifier.h> 00082 #include <llvm/Support/CFG.h> 00083 #include <clang/Frontend/CompilerInstance.h> 00084 #include <clang/Frontend/TextDiagnosticPrinter.h> 00085 #include <clang/Frontend/Utils.h> 00086 #include <clang/Basic/TargetInfo.h> 00087 #include <llvm/Support/ToolOutputFile.h> 00088 #include <llvm/Support/Host.h> 00089 #include <llvm/Assembly/PrintModulePass.h> 00090 #include <llvm/Support/raw_ostream.h> 00091 #include <llvm/Bitcode/ReaderWriter.h> 00092 00093 /*! list of files encountered by the parser. this allows emitting of 00094 the module file's dependencies via the -MMM option */ 00095 std::set<std::string> registeredDependencies; 00096 00097 /*! this is where the parser tells us that it has seen the given file 00098 name in the CPP hash */ 00099 void RegisterDependency(const std::string &fileName) 00100 { 00101 if (fileName[0] != '<' && fileName != "stdlib.ispc") 00102 registeredDependencies.insert(fileName); 00103 } 00104 00105 static void 00106 lDeclareSizeAndPtrIntTypes(SymbolTable *symbolTable) { 00107 const Type *ptrIntType = (g->target.is32Bit) ? AtomicType::VaryingInt32 : 00108 AtomicType::VaryingInt64; 00109 ptrIntType = ptrIntType->GetAsUnboundVariabilityType(); 00110 00111 symbolTable->AddType("intptr_t", ptrIntType, SourcePos()); 00112 symbolTable->AddType("uintptr_t", ptrIntType->GetAsUnsignedType(), 00113 SourcePos()); 00114 symbolTable->AddType("ptrdiff_t", ptrIntType, SourcePos()); 00115 00116 const Type *sizeType = (g->target.is32Bit || g->opt.force32BitAddressing) ? 00117 AtomicType::VaryingUInt32 : AtomicType::VaryingUInt64; 00118 sizeType = sizeType->GetAsUnboundVariabilityType(); 00119 symbolTable->AddType("size_t", sizeType, SourcePos()); 00120 } 00121 00122 00123 /** After compilation completes, there's often a lot of extra debugging 00124 metadata left around that isn't needed any more--for example, for 00125 static functions that weren't actually used, function information for 00126 functions that were inlined, etc. This function takes a llvm::Module 00127 and tries to strip out all of this extra stuff. 00128 */ 00129 static void 00130 lStripUnusedDebugInfo(llvm::Module *module) { 00131 if (g->generateDebuggingSymbols == false) 00132 return; 00133 00134 #ifndef LLVM_3_0 00135 // loop over the compile units that contributed to the final module 00136 if (llvm::NamedMDNode *cuNodes = module->getNamedMetadata("llvm.dbg.cu")) { 00137 for (unsigned i = 0, ie = cuNodes->getNumOperands(); i != ie; ++i) { 00138 llvm::MDNode *cuNode = cuNodes->getOperand(i); 00139 llvm::DICompileUnit cu(cuNode); 00140 llvm::DIArray subprograms = cu.getSubprograms(); 00141 std::vector<llvm::Value *> usedSubprograms; 00142 00143 if (subprograms.getNumElements() == 0) 00144 continue; 00145 00146 // And now loop over the subprograms inside each compile unit. 00147 for (unsigned j = 0, je = subprograms.getNumElements(); j != je; ++j) { 00148 llvm::MDNode *spNode = 00149 llvm::dyn_cast<llvm::MDNode>(subprograms->getOperand(j)); 00150 Assert(spNode != NULL); 00151 llvm::DISubprogram sp(spNode); 00152 00153 // Get the name of the subprogram. Start with the mangled 00154 // name; if that's empty then we have an export'ed 00155 // function, so grab the unmangled name in that case. 00156 std::string name = sp.getLinkageName(); 00157 if (name == "") 00158 name = sp.getName(); 00159 00160 // Does the llvm::Function for this function survive in the 00161 // module? 00162 if (module->getFunction(name) != NULL) 00163 usedSubprograms.push_back(sp); 00164 } 00165 00166 Debug(SourcePos(), "%d / %d functions left in module with debug " 00167 "info.", (int)usedSubprograms.size(), 00168 (int)subprograms.getNumElements()); 00169 00170 // We'd now like to replace the array of subprograms in the 00171 // compile unit with only the ones that actually have function 00172 // definitions present. Unfortunately, llvm::DICompileUnit 00173 // doesn't provide a method to set the subprograms. Therefore, 00174 // we end up needing to directly stuff a new array into the 00175 // appropriate slot (number 12) in the MDNode for the compile 00176 // unit. 00177 // 00178 // Because this is all so hard-coded and would break if the 00179 // debugging metadata organization on the LLVM side changed, 00180 // here is a bunch of asserting to make sure that element 12 of 00181 // the compile unit's MDNode has the subprograms array.... 00182 llvm::MDNode *nodeSPMD = 00183 llvm::dyn_cast<llvm::MDNode>(cuNode->getOperand(12)); 00184 Assert(nodeSPMD != NULL); 00185 llvm::MDNode *nodeSPMDArray = 00186 llvm::dyn_cast<llvm::MDNode>(nodeSPMD->getOperand(0)); 00187 llvm::DIArray nodeSPs(nodeSPMDArray); 00188 Assert(nodeSPs.getNumElements() == subprograms.getNumElements()); 00189 for (int i = 0; i < (int)nodeSPs.getNumElements(); ++i) 00190 Assert(nodeSPs.getElement(i) == subprograms.getElement(i)); 00191 00192 // And now we can go and stuff it into the node with some 00193 // confidence... 00194 llvm::Value *usedSubprogramsArray = 00195 m->diBuilder->getOrCreateArray(llvm::ArrayRef<llvm::Value *>(usedSubprograms)); 00196 llvm::MDNode *replNode = 00197 llvm::MDNode::get(*g->ctx, llvm::ArrayRef<llvm::Value *>(usedSubprogramsArray)); 00198 cuNode->replaceOperandWith(12, replNode); 00199 } 00200 } 00201 00202 // Also, erase a bunch of named metadata detrius; for each function 00203 // there is sometimes named metadata llvm.dbg.lv.{funcname} that 00204 // doesn't seem to be otherwise needed. 00205 std::vector<llvm::NamedMDNode *> toErase; 00206 llvm::Module::named_metadata_iterator iter = module->named_metadata_begin(); 00207 for (; iter != module->named_metadata_end(); ++iter) { 00208 if (!strncmp(iter->getName().str().c_str(), "llvm.dbg.lv", 11)) 00209 toErase.push_back(iter); 00210 } 00211 for (int i = 0; i < (int)toErase.size(); ++i) 00212 module->eraseNamedMetadata(toErase[i]); 00213 #endif // !LLVM_3_0 00214 00215 // Wrap up by running the LLVM pass to remove anything left that's 00216 // unused. 00217 llvm::PassManager pm; 00218 pm.add(llvm::createStripDeadDebugInfoPass()); 00219 pm.run(*module); 00220 } 00221 00222 00223 /////////////////////////////////////////////////////////////////////////// 00224 // Module 00225 00226 Module::Module(const char *fn) { 00227 // It's a hack to do this here, but it must be done after the target 00228 // information has been set (so e.g. the vector width is known...) In 00229 // particular, if we're compiling to multiple targets with different 00230 // vector widths, this needs to be redone each time through. 00231 InitLLVMUtil(g->ctx, g->target); 00232 00233 filename = fn; 00234 errorCount = 0; 00235 symbolTable = new SymbolTable; 00236 ast = new AST; 00237 00238 lDeclareSizeAndPtrIntTypes(symbolTable); 00239 00240 module = new llvm::Module(filename ? filename : "<stdin>", *g->ctx); 00241 module->setTargetTriple(g->target.GetTripleString()); 00242 00243 if (g->target.isa == Target::GENERIC) { 00244 // <16 x i1> vectors only need 16 bit / 2 byte alignment 00245 std::string datalayout = module->getDataLayout(); 00246 datalayout += "v16:16:16"; 00247 module->setDataLayout(datalayout); 00248 } 00249 00250 if (g->generateDebuggingSymbols) { 00251 diBuilder = new llvm::DIBuilder(*module); 00252 00253 // Let the DIBuilder know that we're starting a new compilation 00254 // unit. 00255 if (filename == NULL) { 00256 // Unfortunately we can't yet call Error() since the global 'm' 00257 // variable hasn't been initialized yet. 00258 fprintf(stderr, "Can't emit debugging information with no " 00259 "source file on disk.\n"); 00260 ++errorCount; 00261 delete diBuilder; 00262 diBuilder = NULL; 00263 } 00264 else { 00265 std::string directory, name; 00266 GetDirectoryAndFileName(g->currentDirectory, filename, &directory, 00267 &name); 00268 char producerString[512]; 00269 #if defined(BUILD_VERSION) && defined (BUILD_DATE) 00270 sprintf(producerString, "ispc version %s (build %s on %s)", 00271 ISPC_VERSION, BUILD_VERSION, BUILD_DATE); 00272 #else 00273 sprintf(producerString, "ispc version %s (built on %s)", 00274 ISPC_VERSION, __DATE__); 00275 #endif 00276 diBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C99, /* lang */ 00277 name, /* filename */ 00278 directory, /* directory */ 00279 producerString, /* producer */ 00280 g->opt.level > 0 /* is optimized */, 00281 "-g", /* command line args */ 00282 0 /* run time version */); 00283 } 00284 } 00285 else 00286 diBuilder = NULL; 00287 } 00288 00289 00290 extern FILE *yyin; 00291 extern int yyparse(); 00292 typedef struct yy_buffer_state *YY_BUFFER_STATE; 00293 extern void yy_switch_to_buffer(YY_BUFFER_STATE); 00294 extern YY_BUFFER_STATE yy_scan_string(const char *); 00295 extern YY_BUFFER_STATE yy_create_buffer(FILE *, int); 00296 extern void yy_delete_buffer(YY_BUFFER_STATE); 00297 00298 int 00299 Module::CompileFile() { 00300 extern void ParserInit(); 00301 ParserInit(); 00302 00303 // FIXME: it'd be nice to do this in the Module constructor, but this 00304 // function ends up calling into routines that expect the global 00305 // variable 'm' to be initialized and available (which it isn't until 00306 // the Module constructor returns...) 00307 DefineStdlib(symbolTable, g->ctx, module, g->includeStdlib); 00308 00309 bool runPreprocessor = g->runCPP; 00310 00311 if (runPreprocessor) { 00312 if (filename != NULL) { 00313 // Try to open the file first, since otherwise we crash in the 00314 // preprocessor if the file doesn't exist. 00315 FILE *f = fopen(filename, "r"); 00316 if (!f) { 00317 perror(filename); 00318 return 1; 00319 } 00320 fclose(f); 00321 } 00322 00323 std::string buffer; 00324 llvm::raw_string_ostream os(buffer); 00325 execPreprocessor((filename != NULL) ? filename : "-", &os); 00326 YY_BUFFER_STATE strbuf = yy_scan_string(os.str().c_str()); 00327 yyparse(); 00328 yy_delete_buffer(strbuf); 00329 } 00330 else { 00331 // No preprocessor, just open up the file if it's not stdin.. 00332 FILE* f = NULL; 00333 if (filename == NULL) 00334 f = stdin; 00335 else { 00336 f = fopen(filename, "r"); 00337 if (f == NULL) { 00338 perror(filename); 00339 return 1; 00340 } 00341 } 00342 yyin = f; 00343 yy_switch_to_buffer(yy_create_buffer(yyin, 4096)); 00344 yyparse(); 00345 fclose(f); 00346 } 00347 00348 ast->GenerateIR(); 00349 00350 if (errorCount == 0) 00351 Optimize(module, g->opt.level); 00352 00353 return errorCount; 00354 } 00355 00356 00357 void 00358 Module::AddTypeDef(const std::string &name, const Type *type, 00359 SourcePos pos) { 00360 // Typedefs are easy; just add the mapping between the given name and 00361 // the given type. 00362 symbolTable->AddType(name.c_str(), type, pos); 00363 } 00364 00365 00366 void 00367 Module::AddGlobalVariable(const std::string &name, const Type *type, Expr *initExpr, 00368 bool isConst, StorageClass storageClass, SourcePos pos) { 00369 // These may be NULL due to errors in parsing; just gracefully return 00370 // here if so. 00371 if (name == "" || type == NULL) { 00372 Assert(errorCount > 0); 00373 return; 00374 } 00375 00376 if (symbolTable->LookupFunction(name.c_str())) { 00377 Error(pos, "Global variable \"%s\" shadows previously-declared " 00378 "function.", name.c_str()); 00379 return; 00380 } 00381 00382 if (storageClass == SC_EXTERN_C) { 00383 Error(pos, "extern \"C\" qualifier can only be used for " 00384 "functions."); 00385 return; 00386 } 00387 00388 if (Type::Equal(type, AtomicType::Void)) { 00389 Error(pos, "\"void\" type global variable is illegal."); 00390 return; 00391 } 00392 00393 type = ArrayType::SizeUnsizedArrays(type, initExpr); 00394 if (type == NULL) 00395 return; 00396 00397 const ArrayType *at = CastType<ArrayType>(type); 00398 if (at != NULL && at->TotalElementCount() == 0) { 00399 Error(pos, "Illegal to declare a global variable with unsized " 00400 "array dimensions that aren't set with an initializer " 00401 "expression."); 00402 return; 00403 } 00404 00405 llvm::Type *llvmType = type->LLVMType(g->ctx); 00406 if (llvmType == NULL) 00407 return; 00408 00409 // See if we have an initializer expression for the global. If so, 00410 // make sure it's a compile-time constant! 00411 llvm::Constant *llvmInitializer = NULL; 00412 ConstExpr *constValue = NULL; 00413 if (storageClass == SC_EXTERN || storageClass == SC_EXTERN_C) { 00414 if (initExpr != NULL) 00415 Error(pos, "Initializer can't be provided with \"extern\" " 00416 "global variable \"%s\".", name.c_str()); 00417 } 00418 else { 00419 if (initExpr != NULL) { 00420 initExpr = TypeCheck(initExpr); 00421 if (initExpr != NULL) { 00422 // We need to make sure the initializer expression is 00423 // the same type as the global. (But not if it's an 00424 // ExprList; they don't have types per se / can't type 00425 // convert themselves anyway.) 00426 if (dynamic_cast<ExprList *>(initExpr) == NULL) 00427 initExpr = TypeConvertExpr(initExpr, type, "initializer"); 00428 00429 if (initExpr != NULL) { 00430 initExpr = Optimize(initExpr); 00431 // Fingers crossed, now let's see if we've got a 00432 // constant value.. 00433 llvmInitializer = initExpr->GetConstant(type); 00434 00435 if (llvmInitializer != NULL) { 00436 if (type->IsConstType()) 00437 // Try to get a ConstExpr associated with 00438 // the symbol. This dynamic_cast can 00439 // validly fail, for example for types like 00440 // StructTypes where a ConstExpr can't 00441 // represent their values. 00442 constValue = dynamic_cast<ConstExpr *>(initExpr); 00443 } 00444 else 00445 Error(initExpr->pos, "Initializer for global variable \"%s\" " 00446 "must be a constant.", name.c_str()); 00447 } 00448 } 00449 } 00450 00451 // If no initializer was provided or if we couldn't get a value 00452 // above, initialize it with zeros.. 00453 if (llvmInitializer == NULL) 00454 llvmInitializer = llvm::Constant::getNullValue(llvmType); 00455 } 00456 00457 Symbol *sym = symbolTable->LookupVariable(name.c_str()); 00458 llvm::GlobalVariable *oldGV = NULL; 00459 if (sym != NULL) { 00460 // We've already seen either a declaration or a definition of this 00461 // global. 00462 00463 // If the type doesn't match with the previous one, issue an error. 00464 if (!Type::Equal(sym->type, type) || 00465 (sym->storageClass != SC_EXTERN && 00466 sym->storageClass != SC_EXTERN_C && 00467 sym->storageClass != storageClass)) { 00468 Error(pos, "Definition of variable \"%s\" conflicts with " 00469 "definition at %s:%d.", name.c_str(), 00470 sym->pos.name, sym->pos.first_line); 00471 return; 00472 } 00473 00474 llvm::GlobalVariable *gv = 00475 llvm::dyn_cast<llvm::GlobalVariable>(sym->storagePtr); 00476 Assert(gv != NULL); 00477 00478 // And issue an error if this is a redefinition of a variable 00479 if (gv->hasInitializer() && 00480 sym->storageClass != SC_EXTERN && sym->storageClass != SC_EXTERN_C) { 00481 Error(pos, "Redefinition of variable \"%s\" is illegal. " 00482 "(Previous definition at %s:%d.)", sym->name.c_str(), 00483 sym->pos.name, sym->pos.first_line); 00484 return; 00485 } 00486 00487 // Now, we either have a redeclaration of a global, or a definition 00488 // of a previously-declared global. First, save the pointer to the 00489 // previous llvm::GlobalVariable 00490 oldGV = gv; 00491 } 00492 else { 00493 sym = new Symbol(name, pos, type, storageClass); 00494 symbolTable->AddVariable(sym); 00495 } 00496 sym->constValue = constValue; 00497 00498 llvm::GlobalValue::LinkageTypes linkage = 00499 (sym->storageClass == SC_STATIC) ? llvm::GlobalValue::InternalLinkage : 00500 llvm::GlobalValue::ExternalLinkage; 00501 00502 // Note that the NULL llvmInitializer is what leads to "extern" 00503 // declarations coming up extern and not defining storage (a bit 00504 // subtle)... 00505 sym->storagePtr = new llvm::GlobalVariable(*module, llvmType, isConst, 00506 linkage, llvmInitializer, 00507 sym->name.c_str()); 00508 00509 // Patch up any references to the previous GlobalVariable (e.g. from a 00510 // declaration of a global that was later defined.) 00511 if (oldGV != NULL) { 00512 oldGV->replaceAllUsesWith(sym->storagePtr); 00513 oldGV->removeFromParent(); 00514 sym->storagePtr->setName(sym->name.c_str()); 00515 } 00516 00517 if (diBuilder) { 00518 llvm::DIFile file = pos.GetDIFile(); 00519 llvm::DIGlobalVariable var = 00520 diBuilder->createGlobalVariable(name, 00521 file, 00522 pos.first_line, 00523 sym->type->GetDIType(file), 00524 (sym->storageClass == SC_STATIC), 00525 sym->storagePtr); 00526 Assert(var.Verify()); 00527 } 00528 } 00529 00530 00531 /** Given an arbitrary type, see if it or any of the leaf types contained 00532 in it has a type that's illegal to have exported to C/C++ 00533 code--specifically, that it has a varying value in memory, or a pointer 00534 to SOA data (which has a different representation than a regular 00535 pointer. 00536 00537 (Note that it's fine for the original struct or a contained struct to 00538 be varying, so long as all of its members have bound 'uniform' 00539 variability.) 00540 00541 This functions returns true and issues an error if are any illegal 00542 types are found and returns false otherwise. 00543 */ 00544 static bool 00545 lRecursiveCheckValidParamType(const Type *t) { 00546 const StructType *st = CastType<StructType>(t); 00547 if (st != NULL) { 00548 for (int i = 0; i < st->GetElementCount(); ++i) 00549 if (lRecursiveCheckValidParamType(st->GetElementType(i))) 00550 return true; 00551 return false; 00552 } 00553 00554 const SequentialType *seqt = CastType<SequentialType>(t); 00555 if (seqt != NULL) 00556 return lRecursiveCheckValidParamType(seqt->GetElementType()); 00557 00558 const PointerType *pt = CastType<PointerType>(t); 00559 if (pt != NULL) { 00560 if (pt->IsSlice() || pt->IsVaryingType()) 00561 return true; 00562 return lRecursiveCheckValidParamType(pt->GetBaseType()); 00563 } 00564 00565 return t->IsVaryingType(); 00566 } 00567 00568 00569 /** Given a Symbol representing a function parameter, see if it or any 00570 contained types are varying. If so, issue an error. (This function 00571 should only be called for parameters to 'export'ed functions, where 00572 varying parameters is illegal. 00573 */ 00574 static void 00575 lCheckForVaryingParameter(const Type *type, const std::string &name, 00576 SourcePos pos) { 00577 if (lRecursiveCheckValidParamType(type)) { 00578 if (CastType<PointerType>(type)) 00579 Error(pos, "Varying pointer type parameter \"%s\" is illegal " 00580 "in an exported function.", name.c_str()); 00581 else if (CastType<StructType>(type->GetBaseType())) 00582 Error(pos, "Struct parameter \"%s\" with varying member(s) is illegal " 00583 "in an exported function.", name.c_str()); 00584 else 00585 Error(pos, "Varying parameter \"%s\" is illegal in an exported function.", 00586 name.c_str()); 00587 } 00588 } 00589 00590 00591 /** Given a function type, loop through the function parameters and see if 00592 any are StructTypes. If so, issue an error; this is currently broken 00593 (https://github.com/ispc/ispc/issues/3). 00594 */ 00595 static void 00596 lCheckForStructParameters(const FunctionType *ftype, SourcePos pos) { 00597 for (int i = 0; i < ftype->GetNumParameters(); ++i) { 00598 const Type *type = ftype->GetParameterType(i); 00599 if (CastType<StructType>(type) != NULL) { 00600 Error(pos, "Passing structs to/from application functions is " 00601 "currently broken. Use a pointer or const pointer to the " 00602 "struct instead for now."); 00603 return; 00604 } 00605 } 00606 } 00607 00608 00609 /** We've got a declaration for a function to process. This function does 00610 all the work of creating the corresponding llvm::Function instance, 00611 adding the symbol for the function to the symbol table and doing 00612 various sanity checks. This function returns true upon success and 00613 false if any errors were encountered. 00614 */ 00615 void 00616 Module::AddFunctionDeclaration(const std::string &name, 00617 const FunctionType *functionType, 00618 StorageClass storageClass, bool isInline, 00619 SourcePos pos) { 00620 Assert(functionType != NULL); 00621 00622 // If a global variable with the same name has already been declared 00623 // issue an error. 00624 if (symbolTable->LookupVariable(name.c_str()) != NULL) { 00625 Error(pos, "Function \"%s\" shadows previously-declared global variable. " 00626 "Ignoring this definition.", 00627 name.c_str()); 00628 return; 00629 } 00630 00631 std::vector<Symbol *> overloadFuncs; 00632 symbolTable->LookupFunction(name.c_str(), &overloadFuncs); 00633 if (overloadFuncs.size() > 0) { 00634 for (unsigned int i = 0; i < overloadFuncs.size(); ++i) { 00635 Symbol *overloadFunc = overloadFuncs[i]; 00636 00637 const FunctionType *overloadType = 00638 CastType<FunctionType>(overloadFunc->type); 00639 if (overloadType == NULL) { 00640 Assert(m->errorCount == 0); 00641 continue; 00642 } 00643 00644 // Check for a redeclaration of a function with the same name 00645 // and type. This also hits when we have previously declared 00646 // the function and are about to define it. 00647 if (Type::Equal(overloadFunc->type, functionType)) 00648 return; 00649 00650 if (functionType->isExported || overloadType->isExported) 00651 Error(pos, "Illegal to provide \"export\" qualifier for " 00652 "functions with the same name but different types. " 00653 "(Previous function declaration (%s:%d).)", 00654 overloadFunc->pos.name, overloadFunc->pos.first_line); 00655 00656 // If all of the parameter types match but the return type is 00657 // different, return an error--overloading by return type isn't 00658 // allowed. 00659 const FunctionType *ofType = 00660 CastType<FunctionType>(overloadFunc->type); 00661 Assert(ofType != NULL); 00662 if (ofType->GetNumParameters() == functionType->GetNumParameters()) { 00663 int i; 00664 for (i = 0; i < functionType->GetNumParameters(); ++i) { 00665 if (Type::Equal(ofType->GetParameterType(i), 00666 functionType->GetParameterType(i)) == false) 00667 break; 00668 } 00669 if (i == functionType->GetNumParameters()) { 00670 std::string thisRetType = functionType->GetReturnTypeString(); 00671 std::string otherRetType = ofType->GetReturnTypeString(); 00672 Error(pos, "Illegal to overload function by return " 00673 "type only. This function returns \"%s\" while " 00674 "previous declaration at %s:%d returns \"%s\".", 00675 thisRetType.c_str(), overloadFunc->pos.name, 00676 overloadFunc->pos.first_line, otherRetType.c_str()); 00677 return; 00678 } 00679 } 00680 } 00681 } 00682 00683 if (storageClass == SC_EXTERN_C) { 00684 // Make sure the user hasn't supplied both an 'extern "C"' and a 00685 // 'task' qualifier with the function 00686 if (functionType->isTask) { 00687 Error(pos, "\"task\" qualifier is illegal with C-linkage extern " 00688 "function \"%s\". Ignoring this function.", name.c_str()); 00689 return; 00690 } 00691 00692 std::vector<Symbol *> funcs; 00693 symbolTable->LookupFunction(name.c_str(), &funcs); 00694 if (funcs.size() > 0) { 00695 if (funcs.size() > 1) { 00696 // Multiple functions with this name have already been declared; 00697 // can't overload here 00698 Error(pos, "Can't overload extern \"C\" function \"%s\"; " 00699 "%d functions with the same name have already been declared.", 00700 name.c_str(), (int)funcs.size()); 00701 return; 00702 } 00703 00704 // One function with the same name has been declared; see if it 00705 // has the same type as this one, in which case it's ok. 00706 if (Type::Equal(funcs[0]->type, functionType)) 00707 return; 00708 else { 00709 Error(pos, "Can't overload extern \"C\" function \"%s\".", 00710 name.c_str()); 00711 return; 00712 } 00713 } 00714 } 00715 00716 // Get the LLVM FunctionType 00717 bool disableMask = (storageClass == SC_EXTERN_C); 00718 llvm::FunctionType *llvmFunctionType = 00719 functionType->LLVMFunctionType(g->ctx, disableMask); 00720 if (llvmFunctionType == NULL) 00721 return; 00722 00723 // And create the llvm::Function 00724 llvm::GlobalValue::LinkageTypes linkage = (storageClass == SC_STATIC || 00725 isInline) ? 00726 llvm::GlobalValue::InternalLinkage : llvm::GlobalValue::ExternalLinkage; 00727 00728 std::string functionName = name; 00729 if (storageClass != SC_EXTERN_C) { 00730 functionName += functionType->Mangle(); 00731 if (g->mangleFunctionsWithTarget) 00732 functionName += g->target.GetISAString(); 00733 } 00734 llvm::Function *function = 00735 llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(), 00736 module); 00737 00738 // Set function attributes: we never throw exceptions 00739 function->setDoesNotThrow(true); 00740 if (storageClass != SC_EXTERN_C && 00741 !g->generateDebuggingSymbols && 00742 isInline) 00743 function->addFnAttr(llvm::Attribute::AlwaysInline); 00744 if (functionType->isTask) 00745 // This also applies transitively to members I think? 00746 function->setDoesNotAlias(1, true); 00747 00748 // Make sure that the return type isn't 'varying' if the function is 00749 // 'export'ed. 00750 if (functionType->isExported && 00751 lRecursiveCheckValidParamType(functionType->GetReturnType())) 00752 Error(pos, "Illegal to return a \"varying\" type from exported " 00753 "function \"%s\"", name.c_str()); 00754 00755 if (functionType->isTask && 00756 Type::Equal(functionType->GetReturnType(), AtomicType::Void) == false) 00757 Error(pos, "Task-qualified functions must have void return type."); 00758 00759 if (functionType->isExported || functionType->isExternC) 00760 lCheckForStructParameters(functionType, pos); 00761 00762 // Loop over all of the arguments; process default values if present 00763 // and do other checks and parameter attribute setting. 00764 bool seenDefaultArg = false; 00765 int nArgs = functionType->GetNumParameters(); 00766 for (int i = 0; i < nArgs; ++i) { 00767 const Type *argType = functionType->GetParameterType(i); 00768 const std::string &argName = functionType->GetParameterName(i); 00769 Expr *defaultValue = functionType->GetParameterDefault(i); 00770 const SourcePos &argPos = functionType->GetParameterSourcePos(i); 00771 00772 // If the function is exported, make sure that the parameter 00773 // doesn't have any varying stuff going on in it. 00774 if (functionType->isExported) 00775 lCheckForVaryingParameter(argType, argName, argPos); 00776 00777 // ISPC assumes that no pointers alias. (It should be possible to 00778 // specify when this is not the case, but this should be the 00779 // default.) Set parameter attributes accordingly. (Only for 00780 // uniform pointers, since varying pointers are int vectors...) 00781 if (!functionType->isTask && 00782 ((CastType<PointerType>(argType) != NULL && 00783 argType->IsUniformType()) || 00784 CastType<ReferenceType>(argType) != NULL)) { 00785 00786 // NOTE: LLVM indexes function parameters starting from 1. 00787 // This is unintuitive. 00788 function->setDoesNotAlias(i+1, true); 00789 #if 0 00790 int align = 4 * RoundUpPow2(g->target.nativeVectorWidth); 00791 function->addAttribute(i+1, llvm::Attribute::constructAlignmentFromInt(align)); 00792 #endif 00793 } 00794 00795 if (symbolTable->LookupFunction(argName.c_str())) 00796 Warning(argPos, "Function parameter \"%s\" shadows a function " 00797 "declared in global scope.", argName.c_str()); 00798 00799 if (defaultValue != NULL) 00800 seenDefaultArg = true; 00801 else if (seenDefaultArg) { 00802 // Once one parameter has provided a default value, then all of 00803 // the following ones must have them as well. 00804 Error(argPos, "Parameter \"%s\" is missing default: all " 00805 "parameters after the first parameter with a default value " 00806 "must have default values as well.", argName.c_str()); 00807 } 00808 } 00809 00810 // If llvm gave us back a Function * with a different name than the one 00811 // we asked for, then there's already a function with that same 00812 // (mangled) name in the llvm::Module. In that case, erase the one we 00813 // tried to add and just work with the one it already had. 00814 if (function->getName() != functionName) { 00815 function->eraseFromParent(); 00816 function = module->getFunction(functionName); 00817 } 00818 00819 // Finally, we know all is good and we can add the function to the 00820 // symbol table 00821 Symbol *funSym = new Symbol(name, pos, functionType, storageClass); 00822 funSym->function = function; 00823 bool ok = symbolTable->AddFunction(funSym); 00824 Assert(ok); 00825 } 00826 00827 00828 void 00829 Module::AddFunctionDefinition(const std::string &name, const FunctionType *type, 00830 Stmt *code) { 00831 Symbol *sym = symbolTable->LookupFunction(name.c_str(), type); 00832 if (sym == NULL || code == NULL) { 00833 Assert(m->errorCount > 0); 00834 return; 00835 } 00836 00837 sym->pos = code->pos; 00838 00839 // FIXME: because we encode the parameter names in the function type, 00840 // we need to override the function type here in case the function had 00841 // earlier been declared with anonymous parameter names but is now 00842 // defined with actual names. This is yet another reason we shouldn't 00843 // include the names in FunctionType... 00844 sym->type = type; 00845 00846 ast->AddFunction(sym, code); 00847 } 00848 00849 00850 void 00851 Module::AddExportedTypes(const std::vector<std::pair<const Type *, 00852 SourcePos> > &types) { 00853 for (int i = 0; i < (int)types.size(); ++i) { 00854 if (CastType<StructType>(types[i].first) == NULL && 00855 CastType<VectorType>(types[i].first) == NULL && 00856 CastType<EnumType>(types[i].first) == NULL) 00857 Error(types[i].second, "Only struct, vector, and enum types, " 00858 "not \"%s\", are allowed in type export lists.", 00859 types[i].first->GetString().c_str()); 00860 else 00861 exportedTypes.push_back(types[i]); 00862 } 00863 } 00864 00865 00866 bool 00867 Module::writeOutput(OutputType outputType, const char *outFileName, 00868 const char *includeFileName) { 00869 if (diBuilder != NULL && outputType != Header) { 00870 diBuilder->finalize(); 00871 00872 lStripUnusedDebugInfo(module); 00873 } 00874 00875 // First, issue a warning if the output file suffix and the type of 00876 // file being created seem to mismatch. This can help catch missing 00877 // command-line arguments specifying the output file type. 00878 const char *suffix = strrchr(outFileName, '.'); 00879 if (suffix != NULL) { 00880 ++suffix; 00881 const char *fileType = NULL; 00882 switch (outputType) { 00883 case Asm: 00884 if (strcasecmp(suffix, "s")) 00885 fileType = "assembly"; 00886 break; 00887 case Bitcode: 00888 if (strcasecmp(suffix, "bc")) 00889 fileType = "LLVM bitcode"; 00890 break; 00891 case Object: 00892 if (strcasecmp(suffix, "o") && strcasecmp(suffix, "obj")) 00893 fileType = "object"; 00894 break; 00895 case CXX: 00896 if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") && 00897 strcasecmp(suffix, "c++") && strcasecmp(suffix, "cxx") && 00898 strcasecmp(suffix, "cpp")) 00899 fileType = "c++"; 00900 break; 00901 case Header: 00902 if (strcasecmp(suffix, "h") && strcasecmp(suffix, "hh") && 00903 strcasecmp(suffix, "hpp")) 00904 fileType = "header"; 00905 break; 00906 case Deps: 00907 break; 00908 case DevStub: 00909 if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") && 00910 strcasecmp(suffix, "c++") && strcasecmp(suffix, "cxx") && 00911 strcasecmp(suffix, "cpp")) 00912 fileType = "dev-side offload stub"; 00913 break; 00914 case HostStub: 00915 if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") && 00916 strcasecmp(suffix, "c++") && strcasecmp(suffix, "cxx") && 00917 strcasecmp(suffix, "cpp")) 00918 fileType = "host-side offload stub"; 00919 break; 00920 default: 00921 Assert(0 /* swtich case not handled */); 00922 return 1; 00923 } 00924 if (fileType != NULL) 00925 fprintf(stderr, "Warning: emitting %s file, but filename \"%s\" " 00926 "has suffix \"%s\"?\n", fileType, outFileName, suffix); 00927 } 00928 00929 if (outputType == Header) 00930 return writeHeader(outFileName); 00931 else if (outputType == Deps) 00932 return writeDeps(outFileName); 00933 else if (outputType == HostStub) 00934 return writeHostStub(outFileName); 00935 else if (outputType == DevStub) 00936 return writeDevStub(outFileName); 00937 else if (outputType == Bitcode) 00938 return writeBitcode(module, outFileName); 00939 else if (outputType == CXX) { 00940 extern bool WriteCXXFile(llvm::Module *module, const char *fn, 00941 int vectorWidth, const char *includeName); 00942 return WriteCXXFile(module, outFileName, g->target.vectorWidth, 00943 includeFileName); 00944 } 00945 else 00946 return writeObjectFileOrAssembly(outputType, outFileName); 00947 } 00948 00949 00950 bool 00951 Module::writeBitcode(llvm::Module *module, const char *outFileName) { 00952 // Get a file descriptor corresponding to where we want the output to 00953 // go. If we open it, it'll be closed by the llvm::raw_fd_ostream 00954 // destructor. 00955 int fd; 00956 if (!strcmp(outFileName, "-")) 00957 fd = 1; // stdout 00958 else { 00959 int flags = O_CREAT|O_WRONLY|O_TRUNC; 00960 #ifdef ISPC_IS_WINDOWS 00961 flags |= O_BINARY; 00962 fd = _open(outFileName, flags, 0644); 00963 #else 00964 fd = open(outFileName, flags, 0644); 00965 #endif // ISPC_IS_WINDOWS 00966 if (fd == -1) { 00967 perror(outFileName); 00968 return false; 00969 } 00970 } 00971 00972 llvm::raw_fd_ostream fos(fd, (fd != 1), false); 00973 llvm::WriteBitcodeToFile(module, fos); 00974 return true; 00975 } 00976 00977 00978 bool 00979 Module::writeObjectFileOrAssembly(OutputType outputType, const char *outFileName) { 00980 llvm::TargetMachine *targetMachine = g->target.GetTargetMachine(); 00981 return writeObjectFileOrAssembly(targetMachine, module, outputType, 00982 outFileName); 00983 } 00984 00985 00986 bool 00987 Module::writeObjectFileOrAssembly(llvm::TargetMachine *targetMachine, 00988 llvm::Module *module, OutputType outputType, 00989 const char *outFileName) { 00990 // Figure out if we're generating object file or assembly output, and 00991 // set binary output for object files 00992 llvm::TargetMachine::CodeGenFileType fileType = (outputType == Object) ? 00993 llvm::TargetMachine::CGFT_ObjectFile : llvm::TargetMachine::CGFT_AssemblyFile; 00994 bool binary = (fileType == llvm::TargetMachine::CGFT_ObjectFile); 00995 unsigned int flags = binary ? llvm::raw_fd_ostream::F_Binary : 0; 00996 00997 std::string error; 00998 llvm::tool_output_file *of = new llvm::tool_output_file(outFileName, error, flags); 00999 if (error.size()) { 01000 fprintf(stderr, "Error opening output file \"%s\".\n", outFileName); 01001 return false; 01002 } 01003 01004 llvm::PassManager pm; 01005 if (const llvm::TargetData *td = targetMachine->getTargetData()) 01006 pm.add(new llvm::TargetData(*td)); 01007 else 01008 pm.add(new llvm::TargetData(module)); 01009 01010 llvm::formatted_raw_ostream fos(of->os()); 01011 llvm::CodeGenOpt::Level optLevel = 01012 (g->opt.level > 0) ? llvm::CodeGenOpt::Aggressive : llvm::CodeGenOpt::None; 01013 01014 if (targetMachine->addPassesToEmitFile(pm, fos, fileType, optLevel)) { 01015 fprintf(stderr, "Fatal error adding passes to emit object file!"); 01016 exit(1); 01017 } 01018 01019 // Finally, run the passes to emit the object file/assembly 01020 pm.run(*module); 01021 01022 // Success; tell tool_output_file to keep the final output file. 01023 of->keep(); 01024 01025 return true; 01026 } 01027 01028 01029 /** Emits a declaration for the given struct to the given file. This 01030 function first makes sure that declarations for any structs that are 01031 (recursively) members of this struct are emitted first. 01032 */ 01033 static void 01034 lEmitStructDecl(const StructType *st, std::vector<const StructType *> *emittedStructs, 01035 FILE *file) { 01036 // Has this struct type already been declared? (This happens if it's a 01037 // member of another struct for which we emitted a declaration 01038 // previously.) 01039 for (int i = 0; i < (int)emittedStructs->size(); ++i) 01040 if (Type::EqualIgnoringConst(st, (*emittedStructs)[i])) 01041 return; 01042 01043 // Otherwise first make sure any contained structs have been declared. 01044 for (int i = 0; i < st->GetElementCount(); ++i) { 01045 const StructType *elementStructType = 01046 CastType<StructType>(st->GetElementType(i)); 01047 if (elementStructType != NULL) 01048 lEmitStructDecl(elementStructType, emittedStructs, file); 01049 } 01050 01051 // And now it's safe to declare this one 01052 emittedStructs->push_back(st); 01053 01054 fprintf(file, "struct %s", st->GetStructName().c_str()); 01055 if (st->GetSOAWidth() > 0) 01056 // This has to match the naming scheme in 01057 // StructType::GetCDeclaration(). 01058 fprintf(file, "_SOA%d", st->GetSOAWidth()); 01059 fprintf(file, " {\n"); 01060 01061 for (int i = 0; i < st->GetElementCount(); ++i) { 01062 const Type *type = st->GetElementType(i)->GetAsNonConstType(); 01063 std::string d = type->GetCDeclaration(st->GetElementName(i)); 01064 fprintf(file, " %s;\n", d.c_str()); 01065 } 01066 fprintf(file, "};\n\n"); 01067 } 01068 01069 01070 /** Given a set of structures that we want to print C declarations of in a 01071 header file, emit their declarations. 01072 */ 01073 static void 01074 lEmitStructDecls(std::vector<const StructType *> &structTypes, FILE *file) { 01075 std::vector<const StructType *> emittedStructs; 01076 for (unsigned int i = 0; i < structTypes.size(); ++i) 01077 lEmitStructDecl(structTypes[i], &emittedStructs, file); 01078 Assert(emittedStructs.size() == structTypes.size()); 01079 } 01080 01081 01082 /** Emit C declarations of enumerator types to the generated header file. 01083 */ 01084 static void 01085 lEmitEnumDecls(const std::vector<const EnumType *> &enumTypes, FILE *file) { 01086 if (enumTypes.size() == 0) 01087 return; 01088 01089 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n"); 01090 fprintf(file, "// Enumerator types with external visibility from ispc code\n"); 01091 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n\n"); 01092 01093 for (unsigned int i = 0; i < enumTypes.size(); ++i) { 01094 std::string declaration = enumTypes[i]->GetCDeclaration(""); 01095 fprintf(file, "%s {\n", declaration.c_str()); 01096 01097 // Print the individual enumerators 01098 for (int j = 0; j < enumTypes[i]->GetEnumeratorCount(); ++j) { 01099 const Symbol *e = enumTypes[i]->GetEnumerator(j); 01100 Assert(e->constValue != NULL); 01101 unsigned int enumValue; 01102 int count = e->constValue->AsUInt32(&enumValue); 01103 Assert(count == 1); 01104 01105 // Always print an initializer to set the value. We could be 01106 // 'clever' here and detect whether the implicit value given by 01107 // one plus the previous enumerator value (or zero, for the 01108 // first enumerator) is the same as the value stored with the 01109 // enumerator, though that doesn't seem worth the trouble... 01110 fprintf(file, " %s = %d%c\n", e->name.c_str(), enumValue, 01111 (j < enumTypes[i]->GetEnumeratorCount() - 1) ? ',' : ' '); 01112 } 01113 fprintf(file, "};\n"); 01114 } 01115 } 01116 01117 01118 /** Print declarations of VectorTypes used in 'export'ed parts of the 01119 program in the header file. 01120 */ 01121 static void 01122 lEmitVectorTypedefs(const std::vector<const VectorType *> &types, FILE *file) { 01123 if (types.size() == 0) 01124 return; 01125 01126 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n"); 01127 fprintf(file, "// Vector types with external visibility from ispc code\n"); 01128 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n\n"); 01129 01130 int align = g->target.nativeVectorWidth * 4; 01131 01132 for (unsigned int i = 0; i < types.size(); ++i) { 01133 std::string baseDecl; 01134 const VectorType *vt = types[i]->GetAsNonConstType(); 01135 if (!vt->IsUniformType()) 01136 // Varying stuff shouldn't be visibile to / used by the 01137 // application, so at least make it not simple to access it by 01138 // not declaring the type here... 01139 continue; 01140 01141 int size = vt->GetElementCount(); 01142 01143 baseDecl = vt->GetBaseType()->GetCDeclaration(""); 01144 fprintf(file, "#ifdef _MSC_VER\n__declspec( align(%d) ) ", align); 01145 fprintf(file, "struct %s%d { %s v[%d]; };\n", baseDecl.c_str(), size, 01146 baseDecl.c_str(), size); 01147 fprintf(file, "#else\n"); 01148 fprintf(file, "struct %s%d { %s v[%d]; } __attribute__ ((aligned(%d)));\n", 01149 baseDecl.c_str(), size, baseDecl.c_str(), size, align); 01150 fprintf(file, "#endif\n"); 01151 } 01152 fprintf(file, "\n"); 01153 } 01154 01155 01156 /** Add the given type to the vector, if that type isn't already in there. 01157 */ 01158 template <typename T> static void 01159 lAddTypeIfNew(const Type *type, std::vector<const T *> *exportedTypes) { 01160 type = type->GetAsNonConstType(); 01161 01162 // Linear search, so this ends up being n^2. It's unlikely this will 01163 // matter in practice, though. 01164 for (unsigned int i = 0; i < exportedTypes->size(); ++i) 01165 if (Type::Equal((*exportedTypes)[i], type)) 01166 return; 01167 01168 const T *castType = CastType<T>(type); 01169 Assert(castType != NULL); 01170 exportedTypes->push_back(castType); 01171 } 01172 01173 01174 /** Given an arbitrary type that appears in the app/ispc interface, add it 01175 to an appropriate vector if it is a struct, enum, or short vector type. 01176 Then, if it's a struct, recursively process its members to do the same. 01177 */ 01178 static void 01179 lGetExportedTypes(const Type *type, 01180 std::vector<const StructType *> *exportedStructTypes, 01181 std::vector<const EnumType *> *exportedEnumTypes, 01182 std::vector<const VectorType *> *exportedVectorTypes) { 01183 const ArrayType *arrayType = CastType<ArrayType>(type); 01184 const StructType *structType = CastType<StructType>(type); 01185 01186 if (CastType<ReferenceType>(type) != NULL) 01187 lGetExportedTypes(type->GetReferenceTarget(), exportedStructTypes, 01188 exportedEnumTypes, exportedVectorTypes); 01189 else if (CastType<PointerType>(type) != NULL) 01190 lGetExportedTypes(type->GetBaseType(), exportedStructTypes, 01191 exportedEnumTypes, exportedVectorTypes); 01192 else if (arrayType != NULL) 01193 lGetExportedTypes(arrayType->GetElementType(), exportedStructTypes, 01194 exportedEnumTypes, exportedVectorTypes); 01195 else if (structType != NULL) { 01196 lAddTypeIfNew(type, exportedStructTypes); 01197 for (int i = 0; i < structType->GetElementCount(); ++i) 01198 lGetExportedTypes(structType->GetElementType(i), exportedStructTypes, 01199 exportedEnumTypes, exportedVectorTypes); 01200 } 01201 else if (CastType<UndefinedStructType>(type) != NULL) 01202 // do nothing 01203 ; 01204 else if (CastType<EnumType>(type) != NULL) 01205 lAddTypeIfNew(type, exportedEnumTypes); 01206 else if (CastType<VectorType>(type) != NULL) 01207 lAddTypeIfNew(type, exportedVectorTypes); 01208 else 01209 Assert(CastType<AtomicType>(type) != NULL); 01210 } 01211 01212 01213 /** Given a set of functions, return the set of structure and vector types 01214 present in the parameters to them. 01215 */ 01216 static void 01217 lGetExportedParamTypes(const std::vector<Symbol *> &funcs, 01218 std::vector<const StructType *> *exportedStructTypes, 01219 std::vector<const EnumType *> *exportedEnumTypes, 01220 std::vector<const VectorType *> *exportedVectorTypes) { 01221 for (unsigned int i = 0; i < funcs.size(); ++i) { 01222 const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type); 01223 // Handle the return type 01224 lGetExportedTypes(ftype->GetReturnType(), exportedStructTypes, 01225 exportedEnumTypes, exportedVectorTypes); 01226 01227 // And now the parameter types... 01228 for (int j = 0; j < ftype->GetNumParameters(); ++j) 01229 lGetExportedTypes(ftype->GetParameterType(j), exportedStructTypes, 01230 exportedEnumTypes, exportedVectorTypes); 01231 } 01232 } 01233 01234 01235 static void 01236 lPrintFunctionDeclarations(FILE *file, const std::vector<Symbol *> &funcs, 01237 bool useExternC=1) { 01238 if (useExternC) 01239 fprintf(file, "#if defined(__cplusplus) && !defined(__ISPC_NO_EXTERN_C)\nextern \"C\" {\n#endif // __cplusplus\n"); 01240 // fprintf(file, "#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n"); 01241 for (unsigned int i = 0; i < funcs.size(); ++i) { 01242 const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type); 01243 Assert(ftype); 01244 std::string decl = ftype->GetCDeclaration(funcs[i]->name); 01245 fprintf(file, " extern %s;\n", decl.c_str()); 01246 } 01247 if (useExternC) 01248 01249 fprintf(file, "#if defined(__cplusplus) && !defined(__ISPC_NO_EXTERN_C)\n} /* end extern C */\n#endif // __cplusplus\n"); 01250 // fprintf(file, "#ifdef __cplusplus\n} /* end extern C */\n#endif // __cplusplus\n"); 01251 } 01252 01253 01254 01255 01256 01257 01258 static bool 01259 lIsExported(const Symbol *sym) { 01260 const FunctionType *ft = CastType<FunctionType>(sym->type); 01261 Assert(ft); 01262 return ft->isExported; 01263 } 01264 01265 01266 static bool 01267 lIsExternC(const Symbol *sym) { 01268 const FunctionType *ft = CastType<FunctionType>(sym->type); 01269 Assert(ft); 01270 return ft->isExternC; 01271 } 01272 01273 01274 bool 01275 Module::writeDeps(const char *fn) { 01276 std::cout << "writing dependencies to file " << fn << std::endl; 01277 FILE *file = fopen(fn,"w"); 01278 if (!file) { 01279 perror("fopen"); 01280 return false; 01281 } 01282 01283 for (std::set<std::string>::const_iterator it=registeredDependencies.begin(); 01284 it != registeredDependencies.end(); 01285 ++it) 01286 fprintf(file,"%s\n",it->c_str()); 01287 return true; 01288 } 01289 01290 01291 std::string emitOffloadParamStruct(const std::string ¶mStructName, 01292 const Symbol *sym, 01293 const FunctionType *fct) 01294 { 01295 std::stringstream out; 01296 out << "struct " << paramStructName << " {" << std::endl; 01297 01298 for (int i=0;i<fct->GetNumParameters();i++) { 01299 const Type *orgParamType = fct->GetParameterType(i); 01300 if (orgParamType->IsPointerType() || orgParamType->IsArrayType()) { 01301 /* we're passing pointers separately -- no pointers in that struct... */ 01302 continue; 01303 } 01304 01305 // const reference parameters can be passed as copies. 01306 const Type *paramType; 01307 if (orgParamType->IsReferenceType()) { 01308 if (!orgParamType->IsConstType()) { 01309 Error(sym->pos,"When emitting offload-stubs, \"export\"ed functions cannot have non-const reference-type parameters.\n"); 01310 } 01311 const ReferenceType *refType 01312 = dynamic_cast<const ReferenceType*>(orgParamType); 01313 paramType = refType->GetReferenceTarget()->GetAsNonConstType(); 01314 } else { 01315 paramType = orgParamType->GetAsNonConstType(); 01316 } 01317 std::string paramName = fct->GetParameterName(i); 01318 std::string paramTypeName = paramType->GetString(); 01319 01320 std::string tmpArgDecl = paramType->GetCDeclaration(paramName); 01321 out << " " << tmpArgDecl << ";" << std::endl; 01322 } 01323 01324 out << "};" << std::endl; 01325 return out.str(); 01326 } 01327 01328 bool 01329 Module::writeDevStub(const char *fn) 01330 { 01331 FILE *file = fopen(fn, "w"); 01332 if (!file) { 01333 perror("fopen"); 01334 return false; 01335 } 01336 fprintf(file, "//\n// %s\n// (device stubs automatically generated by the ispc compiler.)\n", fn); 01337 fprintf(file, "// DO NOT EDIT THIS FILE.\n//\n\n"); 01338 fprintf(file,"#include \"ispc/dev/offload.h\"\n\n"); 01339 01340 fprintf(file, "#include <stdint.h>\n\n"); 01341 01342 // Collect single linear arrays of the *exported* functions (we'll 01343 // treat those as "__kernel"s in IVL -- "extern" functions will only 01344 // be used for dev-dev function calls; only "export" functions will 01345 // get exported to the host 01346 std::vector<Symbol *> exportedFuncs; 01347 m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs); 01348 01349 // Get all of the struct, vector, and enumerant types used as function 01350 // parameters. These vectors may have repeats. 01351 std::vector<const StructType *> exportedStructTypes; 01352 std::vector<const EnumType *> exportedEnumTypes; 01353 std::vector<const VectorType *> exportedVectorTypes; 01354 lGetExportedParamTypes(exportedFuncs, &exportedStructTypes, 01355 &exportedEnumTypes, &exportedVectorTypes); 01356 01357 // And print them 01358 lEmitVectorTypedefs(exportedVectorTypes, file); 01359 lEmitEnumDecls(exportedEnumTypes, file); 01360 lEmitStructDecls(exportedStructTypes, file); 01361 01362 fprintf(file, "#ifdef __cplusplus\n"); 01363 fprintf(file, "namespace ispc {\n"); 01364 fprintf(file, "#endif // __cplusplus\n"); 01365 01366 fprintf(file, "\n"); 01367 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n"); 01368 fprintf(file, "// Functions exported from ispc code\n"); 01369 fprintf(file, "// (so the dev stub knows what to call)\n"); 01370 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n"); 01371 lPrintFunctionDeclarations(file, exportedFuncs, true); 01372 01373 fprintf(file, "#ifdef __cplusplus\n"); 01374 fprintf(file, "}/* end namespace */\n"); 01375 fprintf(file, "#endif // __cplusplus\n"); 01376 01377 fprintf(file, "\n"); 01378 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n"); 01379 fprintf(file, "// actual dev stubs\n"); 01380 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n"); 01381 01382 fprintf(file, "// note(iw): due to some linking issues offload stubs *only* work under C++\n"); 01383 fprintf(file, "extern \"C\" {\n\n"); 01384 for (unsigned int i = 0; i < exportedFuncs.size(); ++i) { 01385 const Symbol *sym = exportedFuncs[i]; 01386 Assert(sym); 01387 const FunctionType *fct = CastType<FunctionType>(sym->type); 01388 Assert(fct); 01389 01390 if (!fct->GetReturnType()->IsVoidType()) { 01391 Error(sym->pos,"When emitting offload-stubs, \"export\"ed functions cannot have non-void return types.\n"); 01392 } 01393 01394 // ------------------------------------------------------- 01395 // first, emit a struct that holds the parameters 01396 // ------------------------------------------------------- 01397 std::string paramStructName = std::string("__ispc_dev_stub_")+sym->name; 01398 std::string paramStruct = emitOffloadParamStruct(paramStructName,sym,fct); 01399 fprintf(file,"%s\n",paramStruct.c_str()); 01400 // ------------------------------------------------------- 01401 // then, emit a fct stub that unpacks the parameters and pointers 01402 // ------------------------------------------------------- 01403 fprintf(file,"void __ispc_dev_stub_%s(\n" 01404 " uint32_t in_BufferCount,\n" 01405 " void** in_ppBufferPointers,\n" 01406 " uint64_t* in_pBufferLengths,\n" 01407 " void* in_pMiscData,\n" 01408 " uint16_t in_MiscDataLength,\n" 01409 " void* in_pReturnValue,\n" 01410 " uint16_t in_ReturnValueLength)\n", 01411 sym->name.c_str() 01412 ); 01413 fprintf(file,"{\n"); 01414 fprintf(file," struct %s args;\n memcpy(&args,in_pMiscData,sizeof(args));\n", 01415 paramStructName.c_str()); 01416 std::stringstream funcall; 01417 01418 funcall << "ispc::" << sym->name << "("; 01419 for (int i=0;i<fct->GetNumParameters();i++) { 01420 // get param type and make it non-const, so we can write while unpacking 01421 // const Type *paramType = fct->GetParameterType(i)->GetAsNonConstType(); 01422 const Type *paramType;// = fct->GetParameterType(i)->GetAsNonConstType(); 01423 const Type *orgParamType = fct->GetParameterType(i); 01424 if (orgParamType->IsReferenceType()) { 01425 if (!orgParamType->IsConstType()) { 01426 Error(sym->pos,"When emitting offload-stubs, \"export\"ed functions cannot have non-const reference-type parameters.\n"); 01427 } 01428 const ReferenceType *refType 01429 = dynamic_cast<const ReferenceType*>(orgParamType); 01430 paramType = refType->GetReferenceTarget()->GetAsNonConstType(); 01431 } else { 01432 paramType = orgParamType->GetAsNonConstType(); 01433 } 01434 01435 std::string paramName = fct->GetParameterName(i); 01436 std::string paramTypeName = paramType->GetString(); 01437 01438 if (i) funcall << ", "; 01439 std::string tmpArgName = std::string("_")+paramName; 01440 if (paramType->IsPointerType() || paramType->IsArrayType()) { 01441 std::string tmpArgDecl = paramType->GetCDeclaration(tmpArgName); 01442 fprintf(file," %s;\n", 01443 tmpArgDecl.c_str()); 01444 fprintf(file," (void *&)%s = ispc_dev_translate_pointer(*in_ppBufferPointers++);\n", 01445 tmpArgName.c_str()); 01446 funcall << tmpArgName; 01447 } else { 01448 funcall << "args." << paramName; 01449 } 01450 } 01451 funcall << ");"; 01452 fprintf(file," %s\n",funcall.str().c_str()); 01453 fprintf(file,"}\n\n"); 01454 } 01455 01456 // end extern "C" 01457 fprintf(file, "}/* end extern C */\n"); 01458 01459 fclose(file); 01460 return true; 01461 } 01462 01463 01464 01465 bool 01466 Module::writeHostStub(const char *fn) 01467 { 01468 FILE *file = fopen(fn, "w"); 01469 if (!file) { 01470 perror("fopen"); 01471 return false; 01472 } 01473 fprintf(file, "//\n// %s\n// (device stubs automatically generated by the ispc compiler.)\n", fn); 01474 fprintf(file, "// DO NOT EDIT THIS FILE.\n//\n\n"); 01475 fprintf(file,"#include \"ispc/host/offload.h\"\n\n"); 01476 fprintf(file,"// note(iw): Host stubs do not get extern C linkage -- dev-side already uses that for the same symbols.\n\n"); 01477 //fprintf(file,"#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n"); 01478 01479 fprintf(file, "#ifdef __cplusplus\nnamespace ispc {\n#endif // __cplusplus\n\n"); 01480 01481 // Collect single linear arrays of the *exported* functions (we'll 01482 // treat those as "__kernel"s in IVL -- "extern" functions will only 01483 // be used for dev-dev function calls; only "export" functions will 01484 // get exported to the host 01485 std::vector<Symbol *> exportedFuncs; 01486 m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs); 01487 01488 // Get all of the struct, vector, and enumerant types used as function 01489 // parameters. These vectors may have repeats. 01490 std::vector<const StructType *> exportedStructTypes; 01491 std::vector<const EnumType *> exportedEnumTypes; 01492 std::vector<const VectorType *> exportedVectorTypes; 01493 lGetExportedParamTypes(exportedFuncs, &exportedStructTypes, 01494 &exportedEnumTypes, &exportedVectorTypes); 01495 01496 // And print them 01497 lEmitVectorTypedefs(exportedVectorTypes, file); 01498 lEmitEnumDecls(exportedEnumTypes, file); 01499 lEmitStructDecls(exportedStructTypes, file); 01500 01501 fprintf(file, "\n"); 01502 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n"); 01503 fprintf(file, "// host-side stubs for dev-side ISPC fucntion(s)\n"); 01504 fprintf(file, "///////////////////////////////////////////////////////////////////////////\n"); 01505 for (unsigned int i = 0; i < exportedFuncs.size(); ++i) { 01506 const Symbol *sym = exportedFuncs[i]; 01507 Assert(sym); 01508 const FunctionType *fct = CastType<FunctionType>(sym->type); 01509 Assert(fct); 01510 01511 // ------------------------------------------------------- 01512 // first, emit a struct that holds the parameters 01513 // ------------------------------------------------------- 01514 std::string paramStructName = std::string("__ispc_dev_stub_")+sym->name; 01515 std::string paramStruct = emitOffloadParamStruct(paramStructName,sym,fct); 01516 fprintf(file,"%s\n",paramStruct.c_str()); 01517 // ------------------------------------------------------- 01518 // then, emit a fct stub that unpacks the parameters and pointers 01519 // ------------------------------------------------------- 01520 01521 std::string decl = fct->GetCDeclaration(sym->name); 01522 fprintf(file, "extern %s {\n", decl.c_str()); 01523 int numPointers = 0; 01524 fprintf(file, " %s __args;\n",paramStructName.c_str()); 01525 01526 // ------------------------------------------------------------------ 01527 // write args, and save pointers for later 01528 // ------------------------------------------------------------------ 01529 std::stringstream pointerArgs; 01530 for (int i=0;i<fct->GetNumParameters();i++) { 01531 const Type *orgParamType = fct->GetParameterType(i); 01532 std::string paramName = fct->GetParameterName(i); 01533 if (orgParamType->IsPointerType() || orgParamType->IsArrayType()) { 01534 /* we're passing pointers separately -- no pointers in that struct... */ 01535 if (numPointers) 01536 pointerArgs << ","; 01537 pointerArgs << "(void*)" << paramName; 01538 numPointers++; 01539 continue; 01540 } 01541 01542 fprintf(file," __args.%s = %s;\n", 01543 paramName.c_str(),paramName.c_str()); 01544 } 01545 // ------------------------------------------------------------------ 01546 // writer pointer list 01547 // ------------------------------------------------------------------ 01548 if (numPointers == 0) 01549 pointerArgs << "NULL"; 01550 fprintf(file," void *ptr_args[] = { %s };\n" ,pointerArgs.str().c_str()); 01551 01552 // ------------------------------------------------------------------ 01553 // ... and call the kernel with those args 01554 // ------------------------------------------------------------------ 01555 fprintf(file," static ispc_kernel_handle_t kernel_handle = NULL;\n"); 01556 fprintf(file," if (!kernel_handle) kernel_handle = ispc_host_get_kernel_handle(\"__ispc_dev_stub_%s\");\n", 01557 sym->name.c_str()); 01558 fprintf(file," assert(kernel_handle);\n"); 01559 fprintf(file, 01560 " ispc_host_call_kernel(kernel_handle,\n" 01561 " &__args, sizeof(__args),\n" 01562 " ptr_args,%i);\n", 01563 numPointers); 01564 fprintf(file,"}\n\n"); 01565 } 01566 01567 // end extern "C" 01568 fprintf(file, "#ifdef __cplusplus\n"); 01569 fprintf(file, "}/* namespace */\n"); 01570 fprintf(file, "#endif // __cplusplus\n"); 01571 // fprintf(file, "#ifdef __cplusplus\n"); 01572 // fprintf(file, "}/* end extern C */\n"); 01573 // fprintf(file, "#endif // __cplusplus\n"); 01574 01575 fclose(file); 01576 return true; 01577 } 01578 01579 01580 bool 01581 Module::writeHeader(const char *fn) { 01582 FILE *f = fopen(fn, "w"); 01583 if (!f) { 01584 perror("fopen"); 01585 return false; 01586 } 01587 fprintf(f, "//\n// %s\n// (Header automatically generated by the ispc compiler.)\n", fn); 01588 fprintf(f, "// DO NOT EDIT THIS FILE.\n//\n\n"); 01589 01590 // Create a nice guard string from the filename, turning any 01591 // non-number/letter characters into underbars 01592 std::string guard = "ISPC_"; 01593 const char *p = fn; 01594 while (*p) { 01595 if (isdigit(*p)) 01596 guard += *p; 01597 else if (isalpha(*p)) 01598 guard += toupper(*p); 01599 else 01600 guard += "_"; 01601 ++p; 01602 } 01603 fprintf(f, "#ifndef %s\n#define %s\n\n", guard.c_str(), guard.c_str()); 01604 01605 fprintf(f, "#include <stdint.h>\n\n"); 01606 01607 if (g->emitInstrumentation) { 01608 fprintf(f, "#define ISPC_INSTRUMENTATION 1\n"); 01609 fprintf(f, "extern \"C\" {\n"); 01610 fprintf(f, " void ISPCInstrument(const char *fn, const char *note, int line, uint64_t mask);\n"); 01611 fprintf(f, "}\n"); 01612 } 01613 01614 // end namespace 01615 fprintf(f, "\n"); 01616 fprintf(f, "\n#ifdef __cplusplus\nnamespace ispc { /* namespace */\n#endif // __cplusplus\n"); 01617 01618 01619 // Collect single linear arrays of the exported and extern "C" 01620 // functions 01621 std::vector<Symbol *> exportedFuncs, externCFuncs; 01622 m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs); 01623 m->symbolTable->GetMatchingFunctions(lIsExternC, &externCFuncs); 01624 01625 // Get all of the struct, vector, and enumerant types used as function 01626 // parameters. These vectors may have repeats. 01627 std::vector<const StructType *> exportedStructTypes; 01628 std::vector<const EnumType *> exportedEnumTypes; 01629 std::vector<const VectorType *> exportedVectorTypes; 01630 lGetExportedParamTypes(exportedFuncs, &exportedStructTypes, 01631 &exportedEnumTypes, &exportedVectorTypes); 01632 lGetExportedParamTypes(externCFuncs, &exportedStructTypes, 01633 &exportedEnumTypes, &exportedVectorTypes); 01634 01635 // Go through the explicitly exported types 01636 for (int i = 0; i < (int)exportedTypes.size(); ++i) { 01637 if (const StructType *st = CastType<StructType>(exportedTypes[i].first)) 01638 exportedStructTypes.push_back(st->GetAsUniformType()); 01639 else if (const EnumType *et = CastType<EnumType>(exportedTypes[i].first)) 01640 exportedEnumTypes.push_back(et->GetAsUniformType()); 01641 else if (const VectorType *vt = CastType<VectorType>(exportedTypes[i].first)) 01642 exportedVectorTypes.push_back(vt->GetAsUniformType()); 01643 else 01644 FATAL("Unexpected type in export list"); 01645 } 01646 01647 // And print them 01648 lEmitVectorTypedefs(exportedVectorTypes, f); 01649 lEmitEnumDecls(exportedEnumTypes, f); 01650 lEmitStructDecls(exportedStructTypes, f); 01651 01652 // emit function declarations for exported stuff... 01653 if (exportedFuncs.size() > 0) { 01654 fprintf(f, "\n"); 01655 fprintf(f, "///////////////////////////////////////////////////////////////////////////\n"); 01656 fprintf(f, "// Functions exported from ispc code\n"); 01657 fprintf(f, "///////////////////////////////////////////////////////////////////////////\n"); 01658 lPrintFunctionDeclarations(f, exportedFuncs); 01659 } 01660 #if 0 01661 if (externCFuncs.size() > 0) { 01662 fprintf(f, "\n"); 01663 fprintf(f, "///////////////////////////////////////////////////////////////////////////\n"); 01664 fprintf(f, "// External C functions used by ispc code\n"); 01665 fprintf(f, "///////////////////////////////////////////////////////////////////////////\n"); 01666 lPrintFunctionDeclarations(f, externCFuncs); 01667 } 01668 #endif 01669 01670 // end namespace 01671 fprintf(f, "\n"); 01672 fprintf(f, "\n#ifdef __cplusplus\n} /* namespace */\n#endif // __cplusplus\n"); 01673 01674 // end guard 01675 fprintf(f, "\n#endif // %s\n", guard.c_str()); 01676 01677 fclose(f); 01678 return true; 01679 } 01680 01681 01682 void 01683 Module::execPreprocessor(const char* infilename, llvm::raw_string_ostream* ostream) const 01684 { 01685 clang::CompilerInstance inst; 01686 inst.createFileManager(); 01687 01688 llvm::raw_fd_ostream stderrRaw(2, false); 01689 01690 clang::TextDiagnosticPrinter *diagPrinter = 01691 new clang::TextDiagnosticPrinter(stderrRaw, clang::DiagnosticOptions()); 01692 llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs(new clang::DiagnosticIDs); 01693 clang::DiagnosticsEngine *diagEngine = 01694 new clang::DiagnosticsEngine(diagIDs, diagPrinter); 01695 inst.setDiagnostics(diagEngine); 01696 01697 clang::TargetOptions &options = inst.getTargetOpts(); 01698 llvm::Triple triple(module->getTargetTriple()); 01699 if (triple.getTriple().empty()) { 01700 #ifdef LLVM_3_0 01701 triple.setTriple(llvm::sys::getHostTriple()); 01702 #else 01703 triple.setTriple(llvm::sys::getDefaultTargetTriple()); 01704 #endif 01705 } 01706 options.Triple = triple.getTriple(); 01707 01708 clang::TargetInfo *target = 01709 clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), options); 01710 01711 inst.setTarget(target); 01712 inst.createSourceManager(inst.getFileManager()); 01713 inst.InitializeSourceManager(infilename); 01714 01715 // Don't remove comments in the preprocessor, so that we can accurately 01716 // track the source file position by handling them ourselves. 01717 inst.getPreprocessorOutputOpts().ShowComments = 1; 01718 01719 clang::HeaderSearchOptions &headerOpts = inst.getHeaderSearchOpts(); 01720 headerOpts.UseBuiltinIncludes = 0; 01721 headerOpts.UseStandardSystemIncludes = 0; 01722 headerOpts.UseStandardCXXIncludes = 0; 01723 if (g->debugPrint) 01724 headerOpts.Verbose = 1; 01725 for (int i = 0; i < (int)g->includePath.size(); ++i) 01726 headerOpts.AddPath(g->includePath[i], clang::frontend::Angled, 01727 true /* is user supplied */, 01728 false /* not a framework */, 01729 true /* ignore sys root */); 01730 01731 clang::PreprocessorOptions &opts = inst.getPreprocessorOpts(); 01732 01733 // Add defs for ISPC and PI 01734 opts.addMacroDef("ISPC"); 01735 opts.addMacroDef("PI=3.1415926535"); 01736 01737 // Add #define for current compilation target 01738 char targetMacro[128]; 01739 sprintf(targetMacro, "ISPC_TARGET_%s", g->target.GetISAString()); 01740 char *p = targetMacro; 01741 while (*p) { 01742 *p = toupper(*p); 01743 ++p; 01744 } 01745 opts.addMacroDef(targetMacro); 01746 01747 if (g->target.is32Bit) 01748 opts.addMacroDef("ISPC_POINTER_SIZE=32"); 01749 else 01750 opts.addMacroDef("ISPC_POINTER_SIZE=64"); 01751 01752 if (g->target.hasHalf) 01753 opts.addMacroDef("ISPC_TARGET_HAS_HALF"); 01754 if (g->target.hasTranscendentals) 01755 opts.addMacroDef("ISPC_TARGET_HAS_TRANSCENDENTALS"); 01756 01757 opts.addMacroDef("ISPC_MAJOR_VERSION=1"); 01758 opts.addMacroDef("ISPC_MINOR_VERSION=3"); 01759 01760 if (g->includeStdlib) { 01761 if (g->opt.disableAsserts) 01762 opts.addMacroDef("assert(x)="); 01763 else 01764 opts.addMacroDef("assert(x)=__assert(#x, x)"); 01765 } 01766 01767 for (unsigned int i = 0; i < g->cppArgs.size(); ++i) { 01768 // Sanity check--should really begin with -D 01769 if (g->cppArgs[i].substr(0,2) == "-D") { 01770 opts.addMacroDef(g->cppArgs[i].substr(2)); 01771 } 01772 } 01773 inst.createPreprocessor(); 01774 01775 clang::LangOptions langOptions; 01776 diagPrinter->BeginSourceFile(langOptions, &inst.getPreprocessor()); 01777 clang::DoPrintPreprocessedInput(inst.getPreprocessor(), 01778 ostream, inst.getPreprocessorOutputOpts()); 01779 diagPrinter->EndSourceFile(); 01780 } 01781 01782 01783 // Given an output filename of the form "foo.obj", and an ISA name like 01784 // "avx", return a string with the ISA name inserted before the original 01785 // filename's suffix, like "foo_avx.obj". 01786 static std::string 01787 lGetTargetFileName(const char *outFileName, const char *isaString) { 01788 char *targetOutFileName = new char[strlen(outFileName) + 16]; 01789 if (strrchr(outFileName, '.') != NULL) { 01790 // Copy everything up to the last '.' 01791 int count = strrchr(outFileName, '.') - outFileName; 01792 strncpy(targetOutFileName, outFileName, count); 01793 targetOutFileName[count] = '\0'; 01794 01795 // Add the ISA name 01796 strcat(targetOutFileName, "_"); 01797 strcat(targetOutFileName, isaString); 01798 01799 // And finish with the original file suffiz 01800 strcat(targetOutFileName, strrchr(outFileName, '.')); 01801 } 01802 else { 01803 // Can't find a '.' in the filename, so just append the ISA suffix 01804 // to what we weregiven 01805 strcpy(targetOutFileName, outFileName); 01806 strcat(targetOutFileName, "_"); 01807 strcat(targetOutFileName, isaString); 01808 } 01809 return targetOutFileName; 01810 } 01811 01812 01813 // Given a comma-delimited string with one or more compilation targets of 01814 // the form "sse2,avx-x2", return a vector of strings where each returned 01815 // string holds one of the targets from the given string. 01816 static std::vector<std::string> 01817 lExtractTargets(const char *target) { 01818 std::vector<std::string> targets; 01819 const char *tstart = target; 01820 bool done = false; 01821 while (!done) { 01822 const char *tend = strchr(tstart, ','); 01823 if (tend == NULL) { 01824 done = true; 01825 tend = strchr(tstart, '\0'); 01826 } 01827 targets.push_back(std::string(tstart, tend)); 01828 tstart = tend+1; 01829 } 01830 return targets; 01831 } 01832 01833 01834 static bool 01835 lSymbolIsExported(const Symbol *s) { 01836 return s->exportedFunction != NULL; 01837 } 01838 01839 01840 // Small structure to hold pointers to the various different versions of a 01841 // llvm::Function that were compiled for different compilation target ISAs. 01842 struct FunctionTargetVariants { 01843 FunctionTargetVariants() { 01844 for (int i = 0; i < Target::NUM_ISAS; ++i) 01845 func[i] = NULL; 01846 } 01847 // The func array is indexed with the Target::ISA enumerant. Some 01848 // values may be NULL, indicating that the original function wasn't 01849 // compiled to the corresponding target ISA. 01850 llvm::Function *func[Target::NUM_ISAS]; 01851 }; 01852 01853 01854 // Given the symbol table for a module, return a map from function names to 01855 // FunctionTargetVariants for each function that was defined with the 01856 // 'export' qualifier in ispc. 01857 static void 01858 lGetExportedFunctions(SymbolTable *symbolTable, 01859 std::map<std::string, FunctionTargetVariants> &functions) { 01860 std::vector<Symbol *> syms; 01861 symbolTable->GetMatchingFunctions(lSymbolIsExported, &syms); 01862 for (unsigned int i = 0; i < syms.size(); ++i) { 01863 FunctionTargetVariants &ftv = functions[syms[i]->name]; 01864 ftv.func[g->target.isa] = syms[i]->exportedFunction; 01865 } 01866 } 01867 01868 01869 struct RewriteGlobalInfo { 01870 RewriteGlobalInfo(llvm::GlobalVariable *g = NULL, llvm::Constant *i = NULL, 01871 SourcePos p = SourcePos()) { 01872 gv = g; 01873 init = i; 01874 pos = p; 01875 } 01876 01877 llvm::GlobalVariable *gv; 01878 llvm::Constant *init; 01879 SourcePos pos; 01880 }; 01881 01882 // Grab all of the global value definitions from the module and change them 01883 // to be declarations; we'll emit a single definition of each global in the 01884 // final module used with the dispatch functions, so that we don't have 01885 // multiple definitions of them, one in each of the target-specific output 01886 // files. 01887 static void 01888 lExtractAndRewriteGlobals(llvm::Module *module, 01889 std::vector<RewriteGlobalInfo> *globals) { 01890 llvm::Module::global_iterator iter; 01891 for (iter = module->global_begin(); iter != module->global_end(); ++iter) { 01892 llvm::GlobalVariable *gv = iter; 01893 // Is it a global definition? 01894 if (gv->getLinkage() == llvm::GlobalValue::ExternalLinkage && 01895 gv->hasInitializer()) { 01896 // Turn this into an 'extern 'declaration by clearing its 01897 // initializer. 01898 llvm::Constant *init = gv->getInitializer(); 01899 gv->setInitializer(NULL); 01900 01901 Symbol *sym = 01902 m->symbolTable->LookupVariable(gv->getName().str().c_str()); 01903 Assert(sym != NULL); 01904 globals->push_back(RewriteGlobalInfo(gv, init, sym->pos)); 01905 } 01906 } 01907 } 01908 01909 01910 // This function emits a global variable definition for each global that 01911 // was turned into a declaration in the target-specific output file. 01912 static void 01913 lAddExtractedGlobals(llvm::Module *module, 01914 std::vector<RewriteGlobalInfo> globals[Target::NUM_ISAS]) { 01915 // Find the first element in the globals[] array that has values stored 01916 // in it. All elements of this array should either have empty vectors 01917 // (if we didn't compile to the corresponding ISA or if there are no 01918 // globals), or should have the same number of vector elements as the 01919 // other non-empty vectors. 01920 int firstActive = -1; 01921 for (int i = 0; i < Target::NUM_ISAS; ++i) 01922 if (globals[i].size() > 0) { 01923 firstActive = i; 01924 break; 01925 } 01926 01927 if (firstActive == -1) 01928 // no globals 01929 return; 01930 01931 for (unsigned int i = 0; i < globals[firstActive].size(); ++i) { 01932 RewriteGlobalInfo &rgi = globals[firstActive][i]; 01933 llvm::GlobalVariable *gv = rgi.gv; 01934 llvm::Type *type = gv->getType()->getElementType(); 01935 llvm::Constant *initializer = rgi.init; 01936 01937 // Create a new global in the given model that matches the original 01938 // global 01939 llvm::GlobalVariable *newGlobal = 01940 new llvm::GlobalVariable(*module, type, gv->isConstant(), 01941 llvm::GlobalValue::ExternalLinkage, 01942 initializer, gv->getName()); 01943 newGlobal->copyAttributesFrom(gv); 01944 01945 // For all of the other targets that we actually generated code 01946 // for, make sure the global we just created is compatible with the 01947 // global from the module for that target. 01948 for (int j = firstActive + 1; j < Target::NUM_ISAS; ++j) { 01949 if (globals[j].size() > 0) { 01950 // There should be the same number of globals in the other 01951 // vectors, in the same order. 01952 Assert(globals[firstActive].size() == globals[j].size()); 01953 llvm::GlobalVariable *gv2 = globals[j][i].gv; 01954 Assert(gv2->getName() == gv->getName()); 01955 01956 // It is possible that the types may not match, though--for 01957 // example, this happens with varying globals if we compile 01958 // to different vector widths. 01959 if (gv2->getType() != gv->getType()) 01960 Error(rgi.pos, "Mismatch in size/layout of global " 01961 "variable \"%s\" with different targets. " 01962 "Globals must not include \"varying\" types or arrays " 01963 "with size based on programCount when compiling to " 01964 "targets with differing vector widths.", 01965 gv->getName().str().c_str()); 01966 } 01967 } 01968 } 01969 } 01970 01971 01972 /** Create the dispatch function for an exported ispc function. 01973 This function checks to see which vector ISAs the system the 01974 code is running on supports and calls out to the best available 01975 variant that was generated at compile time. 01976 01977 @param module Module in which to create the dispatch function. 01978 @param setISAFunc Pointer to the __set_system_isa() function defined 01979 in builtins-dispatch.ll (which is linked into the 01980 given module before we get here.) 01981 @param systemBestISAPtr Pointer to the module-local __system_best_isa 01982 variable, which holds a value of the Target::ISA 01983 enumerant giving the most capable ISA that the 01984 system supports. 01985 @param name Name of the function for which we're generating a 01986 dispatch function 01987 @param funcs Target-specific variants of the exported function. 01988 */ 01989 static void 01990 lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc, 01991 llvm::Value *systemBestISAPtr, const std::string &name, 01992 FunctionTargetVariants &funcs) { 01993 // The llvm::Function pointers in funcs are pointers to functions in 01994 // different llvm::Modules, so we can't call them directly. Therefore, 01995 // we'll start by generating an 'extern' declaration of each one that 01996 // we have in the current module so that we can then call out to that. 01997 llvm::Function *targetFuncs[Target::NUM_ISAS]; 01998 llvm::FunctionType *ftype = NULL; 01999 02000 for (int i = 0; i < Target::NUM_ISAS; ++i) { 02001 if (funcs.func[i] == NULL) { 02002 targetFuncs[i] = NULL; 02003 continue; 02004 } 02005 02006 // Grab the type of the function as well. Note that the various 02007 // functions will have different types if they have arguments that 02008 // are pointers to structs, due to the fact that we mangle LLVM 02009 // struct type names with the target vector width. However, 02010 // because we only allow uniform stuff to pass through the 02011 // export'ed function layer, they should all have the same memory 02012 // layout, so this is benign.. 02013 if (ftype == NULL) 02014 ftype = funcs.func[i]->getFunctionType(); 02015 02016 targetFuncs[i] = 02017 llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage, 02018 funcs.func[i]->getName(), module); 02019 } 02020 02021 bool voidReturn = ftype->getReturnType()->isVoidTy(); 02022 02023 // Now we can emit the definition of the dispatch function.. 02024 llvm::Function *dispatchFunc = 02025 llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage, 02026 name.c_str(), module); 02027 llvm::BasicBlock *bblock = 02028 llvm::BasicBlock::Create(*g->ctx, "entry", dispatchFunc); 02029 02030 // Start by calling out to the function that determines the system's 02031 // ISA and sets __system_best_isa, if it hasn't been set yet. 02032 llvm::CallInst::Create(setISAFunc, "", bblock); 02033 02034 // Now we can load the system's ISA enuemrant 02035 llvm::Value *systemISA = 02036 new llvm::LoadInst(systemBestISAPtr, "system_isa", bblock); 02037 02038 // Now emit code that works backwards though the available variants of 02039 // the function. We'll call out to the first one we find that will run 02040 // successfully on the system the code is running on. In working 02041 // through the candidate ISAs here backward, we're taking advantage of 02042 // the expectation that they are ordered in the Target::ISA enumerant 02043 // from least to most capable. 02044 for (int i = Target::NUM_ISAS-1; i >= 0; --i) { 02045 if (targetFuncs[i] == NULL) 02046 continue; 02047 02048 // Emit code to see if the system can run the current candidate 02049 // variant successfully--"is the system's ISA enuemrant value >= 02050 // the enumerant value of the current candidate?" 02051 llvm::Value *ok = 02052 llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_SGE, 02053 systemISA, LLVMInt32(i), "isa_ok", bblock); 02054 llvm::BasicBlock *callBBlock = 02055 llvm::BasicBlock::Create(*g->ctx, "do_call", dispatchFunc); 02056 llvm::BasicBlock *nextBBlock = 02057 llvm::BasicBlock::Create(*g->ctx, "next_try", dispatchFunc); 02058 llvm::BranchInst::Create(callBBlock, nextBBlock, ok, bblock); 02059 02060 // Emit the code to make the call call in callBBlock. 02061 // Just pass through all of the args from the dispatch function to 02062 // the target-specific function. 02063 std::vector<llvm::Value *> args; 02064 llvm::Function::arg_iterator argIter = dispatchFunc->arg_begin(); 02065 for (; argIter != dispatchFunc->arg_end(); ++argIter) 02066 args.push_back(argIter); 02067 if (voidReturn) { 02068 llvm::CallInst::Create(targetFuncs[i], args, "", callBBlock); 02069 llvm::ReturnInst::Create(*g->ctx, callBBlock); 02070 } 02071 else { 02072 llvm::Value *retValue = 02073 llvm::CallInst::Create(targetFuncs[i], args, "ret_value", 02074 callBBlock); 02075 llvm::ReturnInst::Create(*g->ctx, retValue, callBBlock); 02076 } 02077 02078 // Otherwise we'll go on to the next candidate and see about that 02079 // one... 02080 bblock = nextBBlock; 02081 } 02082 02083 // We couldn't find a match that the current system was capable of 02084 // running. We'll call abort(); this is a bit of a blunt hammer--it 02085 // might be preferable to call a user-supplied callback--ISPCError(...) 02086 // or some such, but we don't want to start imposing too much of a 02087 // runtime library requirement either... 02088 llvm::Function *abortFunc = module->getFunction("abort"); 02089 Assert(abortFunc); 02090 llvm::CallInst::Create(abortFunc, "", bblock); 02091 02092 // Return an undef value from the function here; we won't get to this 02093 // point at runtime, but LLVM needs all of the basic blocks to be 02094 // terminated... 02095 if (voidReturn) 02096 llvm::ReturnInst::Create(*g->ctx, bblock); 02097 else { 02098 llvm::Value *undefRet = llvm::UndefValue::get(ftype->getReturnType()); 02099 llvm::ReturnInst::Create(*g->ctx, undefRet, bblock); 02100 } 02101 } 02102 02103 02104 // Given a map that holds the mapping from each of the 'export'ed functions 02105 // in the ispc program to the target-specific variants of the function, 02106 // create a llvm::Module that has a dispatch function for each exported 02107 // function that checks the system's capabilities and picks the most 02108 // appropriate compiled variant of the function. 02109 static llvm::Module * 02110 lCreateDispatchModule(std::map<std::string, FunctionTargetVariants> &functions) { 02111 llvm::Module *module = new llvm::Module("dispatch_module", *g->ctx); 02112 02113 // First, link in the definitions from the builtins-dispatch.ll file. 02114 extern unsigned char builtins_bitcode_dispatch[]; 02115 extern int builtins_bitcode_dispatch_length; 02116 AddBitcodeToModule(builtins_bitcode_dispatch, 02117 builtins_bitcode_dispatch_length, module); 02118 02119 // Get pointers to things we need below 02120 llvm::Function *setFunc = module->getFunction("__set_system_isa"); 02121 Assert(setFunc != NULL); 02122 llvm::Value *systemBestISAPtr = 02123 module->getGlobalVariable("__system_best_isa", true); 02124 Assert(systemBestISAPtr != NULL); 02125 02126 // For each exported function, create the dispatch function 02127 std::map<std::string, FunctionTargetVariants>::iterator iter; 02128 for (iter = functions.begin(); iter != functions.end(); ++iter) 02129 lCreateDispatchFunction(module, setFunc, systemBestISAPtr, 02130 iter->first, iter->second); 02131 02132 // Do some rudimentary cleanup of the final result and make sure that 02133 // the module is all ok. 02134 llvm::PassManager optPM; 02135 optPM.add(llvm::createGlobalDCEPass()); 02136 optPM.add(llvm::createVerifierPass()); 02137 optPM.run(*module); 02138 02139 return module; 02140 } 02141 02142 02143 int 02144 Module::CompileAndOutput(const char *srcFile, 02145 const char *arch, 02146 const char *cpu, 02147 const char *target, 02148 bool generatePIC, 02149 OutputType outputType, 02150 const char *outFileName, 02151 const char *headerFileName, 02152 const char *includeFileName, 02153 const char *depsFileName, 02154 const char *hostStubFileName, 02155 const char *devStubFileName) 02156 { 02157 if (target == NULL || strchr(target, ',') == NULL) { 02158 // We're only compiling to a single target 02159 if (!Target::GetTarget(arch, cpu, target, generatePIC, &g->target)) 02160 return 1; 02161 02162 m = new Module(srcFile); 02163 if (m->CompileFile() == 0) { 02164 if (outFileName != NULL) 02165 if (!m->writeOutput(outputType, outFileName, includeFileName)) 02166 return 1; 02167 if (headerFileName != NULL) 02168 if (!m->writeOutput(Module::Header, headerFileName)) 02169 return 1; 02170 if (depsFileName != NULL) 02171 if (!m->writeOutput(Module::Deps,depsFileName)) 02172 return 1; 02173 if (hostStubFileName != NULL) 02174 if (!m->writeOutput(Module::HostStub,hostStubFileName)) 02175 return 1; 02176 if (devStubFileName != NULL) 02177 if (!m->writeOutput(Module::DevStub,devStubFileName)) 02178 return 1; 02179 } 02180 else 02181 ++m->errorCount; 02182 02183 int errorCount = m->errorCount; 02184 delete m; 02185 m = NULL; 02186 02187 return errorCount > 0; 02188 } 02189 else { 02190 if (outputType == CXX) { 02191 Error(SourcePos(), "Illegal to specify more then one target when " 02192 "compiling C++ output."); 02193 return 1; 02194 } 02195 02196 // The user supplied multiple targets 02197 std::vector<std::string> targets = lExtractTargets(target); 02198 Assert(targets.size() > 1); 02199 02200 if (outFileName != NULL && strcmp(outFileName, "-") == 0) { 02201 Error(SourcePos(), "Multi-target compilation can't generate output " 02202 "to stdout. Please provide an output filename.\n"); 02203 return 1; 02204 } 02205 02206 // Make sure that the function names for 'export'ed functions have 02207 // the target ISA appended to them. 02208 g->mangleFunctionsWithTarget = true; 02209 02210 llvm::TargetMachine *targetMachines[Target::NUM_ISAS]; 02211 for (int i = 0; i < Target::NUM_ISAS; ++i) 02212 targetMachines[i] = NULL; 02213 02214 std::map<std::string, FunctionTargetVariants> exportedFunctions; 02215 std::vector<RewriteGlobalInfo> globals[Target::NUM_ISAS]; 02216 int errorCount = 0; 02217 for (unsigned int i = 0; i < targets.size(); ++i) { 02218 if (!Target::GetTarget(arch, cpu, targets[i].c_str(), generatePIC, 02219 &g->target)) 02220 return 1; 02221 02222 // Issue an error if we've already compiled to a variant of 02223 // this target ISA. (It doesn't make sense to compile to both 02224 // avx and avx-x2, for example.) 02225 if (targetMachines[g->target.isa] != NULL) { 02226 Error(SourcePos(), "Can't compile to multiple variants of %s " 02227 "target!\n", g->target.GetISAString()); 02228 return 1; 02229 } 02230 targetMachines[g->target.isa] = g->target.GetTargetMachine(); 02231 02232 m = new Module(srcFile); 02233 if (m->CompileFile() == 0) { 02234 // Grab pointers to the exported functions from the module we 02235 // just compiled, for use in generating the dispatch function 02236 // later. 02237 lGetExportedFunctions(m->symbolTable, exportedFunctions); 02238 02239 lExtractAndRewriteGlobals(m->module, &globals[i]); 02240 02241 if (outFileName != NULL) { 02242 const char *isaName = g->target.GetISAString(); 02243 std::string targetOutFileName = 02244 lGetTargetFileName(outFileName, isaName); 02245 if (!m->writeOutput(outputType, targetOutFileName.c_str())) 02246 return 1; 02247 } 02248 } 02249 errorCount += m->errorCount; 02250 02251 // Only write the generate header file, if desired, the first 02252 // time through the loop here. 02253 if (i == 0 && headerFileName != NULL) 02254 if (!m->writeOutput(Module::Header, headerFileName)) 02255 return 1; 02256 02257 // Important: Don't delete the llvm::Module *m here; we need to 02258 // keep it around so the llvm::Functions *s stay valid for when 02259 // we generate the dispatch module's functions... 02260 } 02261 02262 llvm::Module *dispatchModule = 02263 lCreateDispatchModule(exportedFunctions); 02264 02265 lAddExtractedGlobals(dispatchModule, globals); 02266 02267 // Find the first non-NULL target machine from the targets we 02268 // compiled to above. We'll use this as the target machine for 02269 // compiling the dispatch module--this is safe in that it is the 02270 // least-common-denominator of all of the targets we compiled to. 02271 llvm::TargetMachine *firstTargetMachine = targetMachines[0]; 02272 int i = 1; 02273 while (i < Target::NUM_ISAS && firstTargetMachine == NULL) 02274 firstTargetMachine = targetMachines[i++]; 02275 Assert(firstTargetMachine != NULL); 02276 02277 if (outFileName != NULL) { 02278 if (outputType == Bitcode) 02279 writeBitcode(dispatchModule, outFileName); 02280 else 02281 writeObjectFileOrAssembly(firstTargetMachine, dispatchModule, 02282 outputType, outFileName); 02283 } 02284 02285 return errorCount > 0; 02286 } 02287 }
1.7.5.1