59 #include <sys/types.h> 60 #ifdef ISPC_HOST_IS_WINDOWS 63 #define strcasecmp stricmp 65 #include "llvm/IR/LegacyPassManager.h" 66 #include <clang/Basic/TargetInfo.h> 67 #include <clang/Frontend/CompilerInstance.h> 68 #include <clang/Frontend/TextDiagnosticPrinter.h> 69 #include <clang/Frontend/Utils.h> 70 #include <clang/Lex/PreprocessorOptions.h> 71 #include <llvm/Analysis/TargetTransformInfo.h> 72 #include <llvm/Bitcode/BitcodeWriter.h> 73 #include <llvm/IR/CFG.h> 74 #include <llvm/IR/DataLayout.h> 75 #include <llvm/IR/DerivedTypes.h> 76 #include <llvm/IR/IRPrintingPasses.h> 77 #include <llvm/IR/InstIterator.h> 78 #include <llvm/IR/Instructions.h> 79 #include <llvm/IR/Intrinsics.h> 80 #include <llvm/IR/LLVMContext.h> 81 #include <llvm/IR/Module.h> 82 #include <llvm/IR/Type.h> 83 #include <llvm/IR/Verifier.h> 84 #include <llvm/PassRegistry.h> 85 #include <llvm/Support/FileUtilities.h> 86 #include <llvm/Support/FormattedStream.h> 87 #include <llvm/Support/Host.h> 88 #include <llvm/Support/ToolOutputFile.h> 89 #include <llvm/Support/raw_ostream.h> 90 #include <llvm/Target/TargetMachine.h> 91 #include <llvm/Target/TargetOptions.h> 92 #include <llvm/Transforms/IPO.h> 93 #include <llvm/Transforms/Utils/ValueMapper.h> 102 if (fileName[0] !=
'<' && fileName !=
"stdlib.ispc")
114 const Type *sizeType =
170 "source file on disk.\n");
175 std::string directory, name;
177 char producerString[512];
178 #if defined(BUILD_VERSION) && defined(BUILD_DATE) 179 snprintf(producerString,
sizeof(producerString),
"ispc version %s (build %s on %s)",
ISPC_VERSION,
180 BUILD_VERSION, BUILD_DATE);
182 snprintf(producerString,
sizeof(producerString),
"ispc version %s (built on %s)",
ISPC_VERSION, __DATE__);
184 auto srcFile =
diBuilder->createFile(name, directory);
186 diBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C99,
204 extern void ParserInit();
213 bool runPreprocessor =
g->
runCPP;
215 if (runPreprocessor) {
228 llvm::raw_string_ostream os(buffer);
252 for (llvm::Function &f : *
module)
253 f.addFnAttr(
"no-frame-pointer-elim",
"true");
254 for (llvm::Function &f : *module)
276 if (name ==
"" || type == NULL) {
283 "Global variable \"%s\" shadows previously-declared " 290 Error(pos,
"extern \"C\" qualifier can only be used for " 296 Error(pos,
"\"void\" type global variable is illegal.");
304 const ArrayType *at = CastType<ArrayType>(type);
306 Error(pos,
"Illegal to declare a global variable with unsized " 307 "array dimensions that aren't set with an initializer " 313 if (llvmType == NULL)
318 llvm::Constant *llvmInitializer = NULL;
321 if (initExpr != NULL)
323 "Initializer can't be provided with \"extern\" " 324 "global variable \"%s\".",
327 if (initExpr != NULL) {
329 if (initExpr != NULL) {
334 if (llvm::dyn_cast<ExprList>(initExpr) == NULL)
337 if (initExpr != NULL) {
342 llvmInitializer = initPair.first;
346 if (llvmInitializer != NULL) {
347 if ((storageClass !=
SC_STATIC) && (initPair.second ==
true)) {
350 "Initializer for global variable \"%s\" " 351 "is not a constant for multi-target compilation.",
356 "Initializer for global variable \"%s\" " 357 "is a constant for single-target compilation " 358 "but not for multi-target compilation.",
368 constValue = llvm::dyn_cast<ConstExpr>(initExpr);
371 "Initializer for global variable \"%s\" " 372 "must be a constant.",
380 if (llvmInitializer == NULL)
381 llvmInitializer = llvm::Constant::getNullValue(llvmType);
385 llvm::GlobalVariable *oldGV = NULL;
394 "Definition of variable \"%s\" conflicts with " 395 "definition at %s:%d.",
400 llvm::GlobalVariable *gv = llvm::dyn_cast<llvm::GlobalVariable>(sym->
storagePtr);
406 "Redefinition of variable \"%s\" is illegal. " 407 "(Previous definition at %s:%d.)",
417 sym =
new Symbol(name, pos, type, storageClass);
422 llvm::GlobalValue::LinkageTypes linkage =
423 (sym->
storageClass ==
SC_STATIC) ? llvm::GlobalValue::InternalLinkage : llvm::GlobalValue::ExternalLinkage;
428 sym->
storagePtr =
new llvm::GlobalVariable(*
module, llvmType, isConst, linkage, llvmInitializer, sym->
name.c_str());
434 oldGV->removeFromParent();
441 llvm::GlobalVariable *sym_GV_storagePtr = llvm::dyn_cast<llvm::GlobalVariable>(sym->
storagePtr);
442 Assert(sym_GV_storagePtr);
443 llvm::DIGlobalVariableExpression *var =
diBuilder->createGlobalVariableExpression(
445 sym_GV_storagePtr->addDebugInfo(var);
466 const StructType *st = CastType<StructType>(t);
477 if (vectorOk ==
false && CastType<VectorType>(t) != NULL)
488 if (pt->IsVaryingType())
507 if (CastType<PointerType>(type))
509 "Varying pointer type parameter \"%s\" is illegal " 510 "in an exported function.",
514 "Struct parameter \"%s\" with vector typed " 515 "member(s) is illegal in an exported function.",
517 else if (CastType<VectorType>(type))
519 "Vector-typed parameter \"%s\" is illegal in an exported " 523 Error(pos,
"Varying parameter \"%s\" is illegal in an exported function.", name.c_str());
534 if (CastType<StructType>(type) != NULL) {
535 Error(pos,
"Passing structs to/from application functions by value " 536 "is currently not supported. Use a reference, a const reference, " 537 "a pointer, or a const pointer to the struct instead.");
551 Assert(functionType != NULL);
557 "Function \"%s\" shadows previously-declared global variable. " 558 "Ignoring this definition.",
563 std::vector<Symbol *> overloadFuncs;
565 if (overloadFuncs.size() > 0) {
566 for (
unsigned int i = 0; i < overloadFuncs.size(); ++i) {
567 Symbol *overloadFunc = overloadFuncs[i];
569 const FunctionType *overloadType = CastType<FunctionType>(overloadFunc->
type);
570 if (overloadType == NULL) {
583 "Illegal to provide \"export\" qualifier for " 584 "functions with the same name but different types. " 585 "(Previous function declaration (%s:%d).)",
603 "Illegal to overload function by return " 604 "type only. This function returns \"%s\" while " 605 "previous declaration at %s:%d returns \"%s\".",
607 otherRetType.c_str());
617 if (functionType->
isTask) {
619 "\"task\" qualifier is illegal with C-linkage extern " 620 "function \"%s\". Ignoring this function.",
625 std::vector<Symbol *> funcs;
627 if (funcs.size() > 0) {
628 if (funcs.size() > 1) {
632 "Can't overload extern \"C\" function \"%s\"; " 633 "%d functions with the same name have already been declared.",
634 name.c_str(), (int)funcs.size());
643 Error(pos,
"Can't overload extern \"C\" function \"%s\".", name.c_str());
652 if (llvmFunctionType == NULL)
656 llvm::GlobalValue::LinkageTypes linkage = (storageClass ==
SC_STATIC || isInline)
657 ? llvm::GlobalValue::InternalLinkage
658 : llvm::GlobalValue::ExternalLinkage;
660 std::string functionName = name;
662 functionName += functionType->
Mangle();
668 llvm::Function *
function = llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(),
module);
673 function->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
677 if (isNoInline && isInline) {
678 Error(pos,
"Illegal to use \"noinline\" and \"inline\" qualifiers together on function \"%s\".", name.c_str());
682 function->setDoesNotThrow();
684 function->addFnAttr(llvm::Attribute::AlwaysInline);
688 function->addFnAttr(llvm::Attribute::NoInline);
691 if (functionType->
isTask) {
693 function->addParamAttr(0, llvm::Attribute::NoAlias);
702 "Illegal to return a \"varying\" or vector type from " 703 "exported function \"%s\"",
707 Error(pos,
"Task-qualified functions must have void return type.");
714 bool seenDefaultArg =
false;
716 for (
int i = 0; i < nArgs; ++i) {
733 if (!functionType->
isTask && ((CastType<PointerType>(argType) != NULL && argType->
IsUniformType() &&
736 !CastType<PointerType>(argType)->IsSlice()) ||
738 CastType<ReferenceType>(argType) != NULL)) {
740 function->addParamAttr(i, llvm::Attribute::NoAlias);
743 function->addAttribute(i+1, llvm::Attribute::constructAlignmentFromInt(align));
749 "Function parameter \"%s\" shadows a function " 750 "declared in global scope.",
753 if (defaultValue != NULL)
754 seenDefaultArg =
true;
755 else if (seenDefaultArg) {
759 "Parameter \"%s\" is missing default: all " 760 "parameters after the first parameter with a default value " 761 "must have default values as well.",
770 if (function->getName() != functionName) {
771 function->eraseFromParent();
772 function =
module->getFunction(functionName);
777 Symbol *funSym =
new Symbol(name, pos, functionType, storageClass);
785 if (sym == NULL || code == NULL) {
803 for (
int i = 0; i < (int)types.size(); ++i) {
804 if (CastType<StructType>(types[i].first) == NULL && CastType<VectorType>(types[i].first) == NULL &&
805 CastType<EnumType>(types[i].first) == NULL)
806 Error(types[i].second,
807 "Only struct, vector, and enum types, " 808 "not \"%s\", are allowed in type export lists.",
809 types[i].first->GetString().c_str());
831 llvm::verifyModule(*
module)) {
832 FATAL(
"Resulting module verification failed!");
839 const char *suffix = strrchr(outFileName,
'.');
840 if (suffix != NULL) {
842 const char *fileType = NULL;
843 switch (outputType) {
845 if (strcasecmp(suffix,
"s"))
846 fileType =
"assembly";
849 if (strcasecmp(suffix,
"bc"))
850 fileType =
"LLVM bitcode";
853 if (strcasecmp(suffix,
"ll"))
854 fileType =
"LLVM assembly";
857 if (strcasecmp(suffix,
"o") && strcasecmp(suffix,
"obj"))
861 if (strcasecmp(suffix,
"c") && strcasecmp(suffix,
"cc") && strcasecmp(suffix,
"c++") &&
862 strcasecmp(suffix,
"cxx") && strcasecmp(suffix,
"cpp"))
866 if (strcasecmp(suffix,
"h") && strcasecmp(suffix,
"hh") && strcasecmp(suffix,
"hpp"))
872 if (strcasecmp(suffix,
"c") && strcasecmp(suffix,
"cc") && strcasecmp(suffix,
"c++") &&
873 strcasecmp(suffix,
"cxx") && strcasecmp(suffix,
"cpp"))
874 fileType =
"dev-side offload stub";
877 if (strcasecmp(suffix,
"c") && strcasecmp(suffix,
"cc") && strcasecmp(suffix,
"c++") &&
878 strcasecmp(suffix,
"cxx") && strcasecmp(suffix,
"cpp"))
879 fileType =
"host-side offload stub";
885 if (fileType != NULL)
887 "Emitting %s file, but filename \"%s\" " 888 "has suffix \"%s\"?",
889 fileType, outFileName, suffix);
892 if (outputType ==
Header) {
897 }
else if (outputType ==
Deps)
901 else if (outputType ==
DevStub)
905 else if (outputType ==
CXX) {
911 extern bool WriteCXXFile(llvm::Module *
module,
const char *fn,
int vectorWidth,
const char *includeName);
922 if (!strcmp(outFileName,
"-"))
925 int flags = O_CREAT | O_WRONLY | O_TRUNC;
926 #ifdef ISPC_HOST_IS_WINDOWS 928 fd = _open(outFileName, flags, 0644);
930 fd = open(outFileName, flags, 0644);
931 #endif // ISPC_HOST_IS_WINDOWS 938 llvm::raw_fd_ostream fos(fd, (fd != 1),
false);
940 #if ISPC_LLVM_VERSION < ISPC_LLVM_7_0 941 llvm::WriteBitcodeToFile(module, fos);
943 llvm::WriteBitcodeToFile(*module, fos);
946 module->print(fos,
nullptr);
956 const char *outFileName) {
959 #if ISPC_LLVM_VERSION <= ISPC_LLVM_9_0 960 llvm::TargetMachine::CodeGenFileType fileType =
961 (outputType ==
Object) ? llvm::TargetMachine::CGFT_ObjectFile : llvm::TargetMachine::CGFT_AssemblyFile;
962 bool binary = (fileType == llvm::TargetMachine::CGFT_ObjectFile);
964 llvm::CodeGenFileType fileType = (outputType ==
Object) ? llvm::CGFT_ObjectFile : llvm::CGFT_AssemblyFile;
965 bool binary = (fileType == llvm::CGFT_ObjectFile);
968 llvm::sys::fs::OpenFlags flags = binary ? llvm::sys::fs::F_None : llvm::sys::fs::F_Text;
970 std::error_code
error;
972 std::unique_ptr<llvm::ToolOutputFile> of(
new llvm::ToolOutputFile(outFileName, error, flags));
975 Error(
SourcePos(),
"Cannot open output file \"%s\".\n", outFileName);
979 llvm::legacy::PassManager pm;
982 llvm::raw_fd_ostream &fos(of->os());
983 #if ISPC_LLVM_VERSION == ISPC_LLVM_6_0 984 if (targetMachine->addPassesToEmitFile(pm, fos, fileType)) {
985 FATAL(
"Failed to add passes to emit object file!");
990 if (targetMachine->addPassesToEmitFile(pm, fos,
nullptr, fileType)) {
991 FATAL(
"Failed to add passes to emit object file!");
1008 const StructType *st = CastType<StructType>(t);
1012 const ArrayType *at = CastType<ArrayType>(t);
1022 for (
int j = 0; j < numElts; ++j) {
1037 bool emitUnifs =
true) {
1048 for (
int i = 0; i < (int)emittedStructs->size(); ++i)
1055 if (elementStructType != NULL)
1060 emittedStructs->push_back(st);
1062 fprintf(file,
"#ifndef __ISPC_STRUCT_%s__\n", st->
GetCStructName().c_str());
1063 fprintf(file,
"#define __ISPC_STRUCT_%s__\n", st->
GetCStructName().c_str());
1066 bool pack, needsAlign =
false;
1070 if (!(pack = llvm::dyn_cast<llvm::StructType>(stype)->isPacked()))
1073 needsAlign |= ftype->
IsVaryingType() && (CastType<StructType>(ftype) == NULL);
1078 snprintf(sSOA,
sizeof(sSOA),
"_SOA%d", st->
GetSOAWidth());
1082 fprintf(file,
"%sstruct %s%s {\n", (pack) ?
"packed " :
"", st->
GetCStructName().c_str(), sSOA);
1084 unsigned uABI = DL->getABITypeAlignment(stype);
1085 fprintf(file,
"__ISPC_ALIGNED_STRUCT__(%u) %s%s {\n", uABI, st->
GetCStructName().c_str(), sSOA);
1092 if (needsAlign && ftype->
IsVaryingType() && (CastType<StructType>(ftype) == NULL)) {
1093 unsigned uABI = DL->getABITypeAlignment(ftype->
LLVMType(
g->
ctx));
1094 fprintf(file,
"__ISPC_ALIGN__(%u) ", uABI);
1099 (CastType<StructType>(ftype) == NULL)) {
1102 fprintf(file,
"%s;\n", d.c_str());
1105 fprintf(file,
"};\n");
1106 fprintf(file,
"#endif\n\n");
1112 static void lEmitStructDecls(std::vector<const StructType *> &structTypes, FILE *file,
bool emitUnifs =
true) {
1113 std::vector<const StructType *> emittedStructs;
1115 fprintf(file,
"\n#ifndef __ISPC_ALIGN__\n" 1116 "#if defined(__clang__) || !defined(_MSC_VER)\n" 1117 "// Clang, GCC, ICC\n" 1118 "#define __ISPC_ALIGN__(s) __attribute__((aligned(s)))\n" 1119 "#define __ISPC_ALIGNED_STRUCT__(s) struct __ISPC_ALIGN__(s)\n" 1121 "// Visual Studio\n" 1122 "#define __ISPC_ALIGN__(s) __declspec(align(s))\n" 1123 "#define __ISPC_ALIGNED_STRUCT__(s) __ISPC_ALIGN__(s) struct\n" 1127 for (
unsigned int i = 0; i < structTypes.size(); ++i)
1133 static void lEmitEnumDecls(
const std::vector<const EnumType *> &enumTypes, FILE *file) {
1134 if (enumTypes.size() == 0)
1137 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n");
1138 fprintf(file,
"// Enumerator types with external visibility from ispc code\n");
1139 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n\n");
1141 for (
unsigned int i = 0; i < enumTypes.size(); ++i) {
1142 fprintf(file,
"#ifndef __ISPC_ENUM_%s__\n", enumTypes[i]->GetEnumName().c_str());
1143 fprintf(file,
"#define __ISPC_ENUM_%s__\n", enumTypes[i]->GetEnumName().c_str());
1144 std::string declaration = enumTypes[i]->GetCDeclaration(
"");
1145 fprintf(file,
"%s {\n", declaration.c_str());
1148 for (
int j = 0; j < enumTypes[i]->GetEnumeratorCount(); ++j) {
1149 const Symbol *e = enumTypes[i]->GetEnumerator(j);
1151 unsigned int enumValue;
1160 fprintf(file,
" %s = %d%c\n", e->
name.c_str(), enumValue,
1161 (j < enumTypes[i]->GetEnumeratorCount() - 1) ?
',' :
' ');
1163 fprintf(file,
"};\n");
1164 fprintf(file,
"#endif\n\n");
1172 if (types.size() == 0)
1175 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n");
1176 fprintf(file,
"// Vector types with external visibility from ispc code\n");
1177 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n\n");
1179 for (
unsigned int i = 0; i < types.size(); ++i) {
1180 std::string baseDecl;
1193 fprintf(file,
"#ifndef __ISPC_VECTOR_%s%d__\n", baseDecl.c_str(), size);
1194 fprintf(file,
"#define __ISPC_VECTOR_%s%d__\n", baseDecl.c_str(), size);
1195 fprintf(file,
"#ifdef _MSC_VER\n__declspec( align(%d) ) ", align);
1196 fprintf(file,
"struct %s%d { %s v[%d]; };\n", baseDecl.c_str(), size, baseDecl.c_str(), size);
1197 fprintf(file,
"#else\n");
1198 fprintf(file,
"struct %s%d { %s v[%d]; } __attribute__ ((aligned(%d)));\n", baseDecl.c_str(), size,
1199 baseDecl.c_str(), size, align);
1200 fprintf(file,
"#endif\n");
1201 fprintf(file,
"#endif\n\n");
1203 fprintf(file,
"\n");
1213 for (
unsigned int i = 0; i < exportedTypes->size(); ++i)
1217 const T *castType = CastType<T>(type);
1218 Assert(castType != NULL);
1219 exportedTypes->push_back(castType);
1227 std::vector<const EnumType *> *exportedEnumTypes,
1228 std::vector<const VectorType *> *exportedVectorTypes) {
1229 const ArrayType *arrayType = CastType<ArrayType>(type);
1230 const StructType *structType = CastType<StructType>(type);
1231 const FunctionType *ftype = CastType<FunctionType>(type);
1233 if (CastType<ReferenceType>(type) != NULL)
1235 else if (CastType<PointerType>(type) != NULL)
1237 else if (arrayType != NULL)
1239 else if (structType != NULL) {
1241 for (
int i = 0; i < structType->GetElementCount(); ++i)
1242 lGetExportedTypes(structType->GetElementType(i), exportedStructTypes, exportedEnumTypes,
1243 exportedVectorTypes);
1244 }
else if (CastType<UndefinedStructType>(type) != NULL)
1247 else if (CastType<EnumType>(type) != NULL)
1249 else if (CastType<VectorType>(type) != NULL)
1251 else if (ftype != NULL) {
1253 lGetExportedTypes(ftype->GetReturnType(), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1256 for (
int j = 0; j < ftype->GetNumParameters(); ++j)
1257 lGetExportedTypes(ftype->GetParameterType(j), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1259 Assert(CastType<AtomicType>(type) != NULL);
1266 std::vector<const StructType *> *exportedStructTypes,
1267 std::vector<const EnumType *> *exportedEnumTypes,
1268 std::vector<const VectorType *> *exportedVectorTypes) {
1269 for (
unsigned int i = 0; i < funcs.size(); ++i) {
1270 const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type);
1284 bool rewriteForDispatch =
false) {
1286 fprintf(file,
"#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern " 1287 "\"C\" {\n#endif // __cplusplus\n");
1289 for (
unsigned int i = 0; i < funcs.size(); ++i) {
1290 const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type);
1293 if (rewriteForDispatch) {
1298 fprintf(file,
" extern %s;\n", decl.c_str());
1302 fprintf(file,
"#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end " 1303 "extern C */\n#endif // __cplusplus\n");
1323 for (std::string::iterator it = str.begin(); it != str.end(); ++it) {
1324 size_t pos = it - str.begin();
1325 std::string::iterator next = it + 1;
1326 if (*it ==
'\\' && next != str.end()) {
1328 #define UNESCAPE_SEQ(c, esc) \ 1332 it = str.begin() + pos; \ 1352 printf(
"\nWriting dependencies to file %s\n", fn);
1354 FILE *file = fn ? fopen(fn,
"w") : stdout;
1360 if (generateMakeRule) {
1361 fprintf(file,
"%s:", tn);
1364 fprintf(file,
" %s", sn);
1366 std::string unescaped;
1373 0 == strcmp(sn, unescaped.c_str()))
1375 fprintf(file,
" \\\n");
1376 fprintf(file,
" %s", unescaped.c_str());
1378 fprintf(file,
"\n");
1382 fprintf(file,
"%s\n", it->c_str());
1389 std::stringstream out;
1390 out <<
"struct " << paramStructName <<
" {" << std::endl;
1400 const Type *paramType;
1403 Error(sym->
pos,
"When emitting offload-stubs, \"export\"ed functions cannot have non-const " 1404 "reference-type parameters.\n");
1412 std::string paramTypeName = paramType->
GetString();
1415 out <<
" " << tmpArgDecl <<
";" << std::endl;
1418 out <<
"};" << std::endl;
1423 FILE *file = fopen(fn,
"w");
1428 fprintf(file,
"//\n// %s\n// (device stubs automatically generated by the ispc compiler.)\n", fn);
1429 fprintf(file,
"// DO NOT EDIT THIS FILE.\n//\n\n");
1430 fprintf(file,
"#include \"ispc/dev/offload.h\"\n\n");
1432 fprintf(file,
"#include <stdint.h>\n\n");
1438 std::vector<Symbol *> exportedFuncs;
1443 std::vector<const StructType *> exportedStructTypes;
1444 std::vector<const EnumType *> exportedEnumTypes;
1445 std::vector<const VectorType *> exportedVectorTypes;
1453 fprintf(file,
"#ifdef __cplusplus\n");
1454 fprintf(file,
"namespace ispc {\n");
1455 fprintf(file,
"#endif // __cplusplus\n");
1457 fprintf(file,
"\n");
1458 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n");
1459 fprintf(file,
"// Functions exported from ispc code\n");
1460 fprintf(file,
"// (so the dev stub knows what to call)\n");
1461 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n");
1464 fprintf(file,
"#ifdef __cplusplus\n");
1465 fprintf(file,
"}/* end namespace */\n");
1466 fprintf(file,
"#endif // __cplusplus\n");
1468 fprintf(file,
"\n");
1469 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n");
1470 fprintf(file,
"// actual dev stubs\n");
1471 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n");
1473 fprintf(file,
"// note(iw): due to some linking issues offload stubs *only* work under C++\n");
1474 fprintf(file,
"extern \"C\" {\n\n");
1475 for (
unsigned int i = 0; i < exportedFuncs.size(); ++i) {
1476 const Symbol *sym = exportedFuncs[i];
1485 "When emitting offload-stubs, ignoring \"export\"ed function with non-void return types.\n");
1492 std::string paramStructName = std::string(
"__ispc_dev_stub_") + sym->
name;
1494 fprintf(file,
"%s\n", paramStruct.c_str());
1499 "void __ispc_dev_stub_%s(\n" 1500 " uint32_t in_BufferCount,\n" 1501 " void** in_ppBufferPointers,\n" 1502 " uint64_t* in_pBufferLengths,\n" 1503 " void* in_pMiscData,\n" 1504 " uint16_t in_MiscDataLength,\n" 1505 " void* in_pReturnValue,\n" 1506 " uint16_t in_ReturnValueLength)\n",
1508 fprintf(file,
"{\n");
1509 fprintf(file,
" struct %s args;\n memcpy(&args,in_pMiscData,sizeof(args));\n", paramStructName.c_str());
1510 std::stringstream funcall;
1512 funcall <<
"ispc::" << sym->
name <<
"(";
1516 const Type *paramType;
1520 Error(sym->
pos,
"When emitting offload-stubs, \"export\"ed functions cannot have non-const " 1521 "reference-type parameters.\n");
1530 std::string paramTypeName = paramType->
GetString();
1534 std::string tmpArgName = std::string(
"_") + paramName;
1537 fprintf(file,
" %s;\n", tmpArgDecl.c_str());
1538 fprintf(file,
" (void *&)%s = ispc_dev_translate_pointer(*in_ppBufferPointers++);\n",
1539 tmpArgName.c_str());
1540 funcall << tmpArgName;
1542 funcall <<
"args." << paramName;
1546 fprintf(file,
" %s\n", funcall.str().c_str());
1547 fprintf(file,
"}\n\n");
1551 fprintf(file,
"}/* end extern C */\n");
1558 FILE *file = fopen(fn,
"w");
1563 fprintf(file,
"//\n// %s\n// (device stubs automatically generated by the ispc compiler.)\n", fn);
1564 fprintf(file,
"// DO NOT EDIT THIS FILE.\n//\n\n");
1565 fprintf(file,
"#include \"ispc/host/offload.h\"\n\n");
1568 "// note(iw): Host stubs do not get extern C linkage -- dev-side already uses that for the same symbols.\n\n");
1571 fprintf(file,
"#ifdef __cplusplus\nnamespace ispc {\n#endif // __cplusplus\n\n");
1577 std::vector<Symbol *> exportedFuncs;
1582 std::vector<const StructType *> exportedStructTypes;
1583 std::vector<const EnumType *> exportedEnumTypes;
1584 std::vector<const VectorType *> exportedVectorTypes;
1592 fprintf(file,
"\n");
1593 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n");
1594 fprintf(file,
"// host-side stubs for dev-side ISPC fucntion(s)\n");
1595 fprintf(file,
"///////////////////////////////////////////////////////////////////////////\n");
1596 for (
unsigned int i = 0; i < exportedFuncs.size(); ++i) {
1597 const Symbol *sym = exportedFuncs[i];
1604 "When emitting offload-stubs, ignoring \"export\"ed function with non-void return types.\n");
1611 std::string paramStructName = std::string(
"__ispc_dev_stub_") + sym->
name;
1613 fprintf(file,
"%s\n", paramStruct.c_str());
1619 fprintf(file,
"extern %s {\n", decl.c_str());
1620 int numPointers = 0;
1621 fprintf(file,
" %s __args;\n", paramStructName.c_str());
1626 std::stringstream pointerArgs;
1634 pointerArgs <<
"(void*)" << paramName;
1639 fprintf(file,
" __args.%s = %s;\n", paramName.c_str(), paramName.c_str());
1644 if (numPointers == 0)
1645 pointerArgs <<
"NULL";
1646 fprintf(file,
" void *ptr_args[] = { %s };\n", pointerArgs.str().c_str());
1651 fprintf(file,
" static ispc_kernel_handle_t kernel_handle = NULL;\n");
1652 fprintf(file,
" if (!kernel_handle) kernel_handle = ispc_host_get_kernel_handle(\"__ispc_dev_stub_%s\");\n",
1654 fprintf(file,
" assert(kernel_handle);\n");
1656 " ispc_host_call_kernel(kernel_handle,\n" 1657 " &__args, sizeof(__args),\n" 1660 fprintf(file,
"}\n\n");
1664 fprintf(file,
"#ifdef __cplusplus\n");
1665 fprintf(file,
"}/* namespace */\n");
1666 fprintf(file,
"#endif // __cplusplus\n");
1676 FILE *f = fopen(fn,
"w");
1681 fprintf(f,
"//\n// %s\n// (Header automatically generated by the ispc compiler.)\n", fn);
1682 fprintf(f,
"// DO NOT EDIT THIS FILE.\n//\n\n");
1686 std::string guard =
"ISPC_";
1691 else if (isalpha(*p))
1692 guard += toupper(*p);
1699 fprintf(f,
"#ifndef %s\n#define %s\n\n", guard.c_str(), guard.c_str());
1701 fprintf(f,
"#pragma once\n");
1703 fprintf(f,
"#include <stdint.h>\n\n");
1706 fprintf(f,
"#define ISPC_INSTRUMENTATION 1\n");
1707 fprintf(f,
"#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern \"C\" " 1708 "{\n#endif // __cplusplus\n");
1709 fprintf(f,
" void ISPCInstrument(const char *fn, const char *note, int line, uint64_t mask);\n");
1710 fprintf(f,
"#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end " 1711 "extern C */\n#endif // __cplusplus\n");
1716 fprintf(f,
"\n#ifdef __cplusplus\nnamespace ispc { /* namespace */\n#endif // __cplusplus\n");
1720 std::vector<Symbol *> exportedFuncs, externCFuncs;
1726 std::vector<const StructType *> exportedStructTypes;
1727 std::vector<const EnumType *> exportedEnumTypes;
1728 std::vector<const VectorType *> exportedVectorTypes;
1735 exportedStructTypes.push_back(st->GetAsUniformType());
1737 exportedEnumTypes.push_back(et->GetAsUniformType());
1739 exportedVectorTypes.push_back(vt->GetAsUniformType());
1741 FATAL(
"Unexpected type in export list");
1750 if (exportedFuncs.size() > 0) {
1752 fprintf(f,
"///////////////////////////////////////////////////////////////////////////\n");
1753 fprintf(f,
"// Functions exported from ispc code\n");
1754 fprintf(f,
"///////////////////////////////////////////////////////////////////////////\n");
1758 if (externCFuncs.size() > 0) {
1760 fprintf(f,
"///////////////////////////////////////////////////////////////////////////\n");
1761 fprintf(f,
"// External C functions used by ispc code\n");
1762 fprintf(f,
"///////////////////////////////////////////////////////////////////////////\n");
1769 fprintf(f,
"\n#ifdef __cplusplus\n} /* namespace */\n#endif // __cplusplus\n");
1773 fprintf(f,
"\n#endif // %s\n", guard.c_str());
1792 FILE *f = DHI->
file;
1795 fprintf(f,
"//\n// %s\n// (Header automatically generated by the ispc compiler.)\n", DHI->
fn);
1796 fprintf(f,
"// DO NOT EDIT THIS FILE.\n//\n\n");
1800 std::string guard =
"ISPC_";
1801 const char *p = DHI->
fn;
1805 else if (isalpha(*p))
1806 guard += toupper(*p);
1813 fprintf(f,
"#ifndef %s\n#define %s\n\n", guard.c_str(), guard.c_str());
1815 fprintf(f,
"#pragma once\n");
1817 fprintf(f,
"#include <stdint.h>\n\n");
1820 fprintf(f,
"#define ISPC_INSTRUMENTATION 1\n");
1821 fprintf(f,
"#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern " 1822 "\"C\" {\n#endif // __cplusplus\n");
1823 fprintf(f,
" void ISPCInstrument(const char *fn, const char *note, int line, uint64_t mask);\n");
1824 fprintf(f,
"#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end " 1825 "extern C */\n#endif // __cplusplus\n");
1830 fprintf(f,
"\n#ifdef __cplusplus\nnamespace ispc { /* namespace */\n#endif // __cplusplus\n\n");
1836 std::vector<Symbol *> exportedFuncs, externCFuncs;
1842 if ((DHI->
Emit4 && (programCount == 4)) || (DHI->
Emit8 && (programCount == 8)) ||
1843 (DHI->
Emit16 && (programCount == 16))) {
1846 std::vector<const StructType *> exportedStructTypes;
1847 std::vector<const EnumType *> exportedEnumTypes;
1848 std::vector<const VectorType *> exportedVectorTypes;
1855 exportedStructTypes.push_back(st->GetAsUniformType());
1857 exportedEnumTypes.push_back(et->GetAsUniformType());
1859 exportedVectorTypes.push_back(vt->GetAsUniformType());
1861 FATAL(
"Unexpected type in export list");
1873 if (programCount == 4) {
1875 }
else if (programCount == 8) {
1877 }
else if (programCount == 16) {
1883 if (exportedFuncs.size() > 0) {
1885 fprintf(f,
"///////////////////////////////////////////////////////////////////////////\n");
1886 fprintf(f,
"// Functions exported from ispc code\n");
1887 fprintf(f,
"///////////////////////////////////////////////////////////////////////////\n");
1897 fprintf(f,
"\n#ifdef __cplusplus\n} /* namespace */\n#endif // __cplusplus\n");
1901 fprintf(f,
"\n#endif // %s\n", guard.c_str());
1908 clang::CompilerInstance inst;
1910 llvm::raw_fd_ostream stderrRaw(2,
false);
1912 clang::DiagnosticOptions *diagOptions =
new clang::DiagnosticOptions();
1913 clang::TextDiagnosticPrinter *diagPrinter =
new clang::TextDiagnosticPrinter(stderrRaw, diagOptions);
1915 llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs(
new clang::DiagnosticIDs);
1916 clang::DiagnosticsEngine *diagEngine =
new clang::DiagnosticsEngine(diagIDs, diagOptions, diagPrinter);
1918 inst.setDiagnostics(diagEngine);
1920 inst.createFileManager();
1922 const std::shared_ptr<clang::TargetOptions> &options = std::make_shared<clang::TargetOptions>(inst.getTargetOpts());
1924 llvm::Triple triple(
module->getTargetTriple());
1925 if (triple.getTriple().empty()) {
1926 triple.setTriple(llvm::sys::getDefaultTargetTriple());
1929 options->Triple = triple.getTriple();
1931 clang::TargetInfo *target = clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), options);
1932 inst.setTarget(target);
1933 inst.createSourceManager(inst.getFileManager());
1935 #if ISPC_LLVM_VERSION <= ISPC_LLVM_9_0 1936 clang::FrontendInputFile inputFile(infilename, clang::InputKind::Unknown);
1938 clang::FrontendInputFile inputFile(infilename, clang::InputKind());
1941 inst.InitializeSourceManager(inputFile);
1945 inst.getPreprocessorOutputOpts().ShowComments = 1;
1947 inst.getPreprocessorOutputOpts().ShowCPP = 1;
1948 clang::HeaderSearchOptions &headerOpts = inst.getHeaderSearchOpts();
1949 headerOpts.UseBuiltinIncludes = 0;
1950 headerOpts.UseStandardSystemIncludes = 0;
1951 headerOpts.UseStandardCXXIncludes = 0;
1952 #ifndef ISPC_NO_DUMPS 1954 headerOpts.Verbose = 1;
1957 headerOpts.AddPath(
g->
includePath[i], clang::frontend::Angled,
false ,
1961 clang::PreprocessorOptions &opts = inst.getPreprocessorOpts();
1964 opts.addMacroDef(
"ISPC");
1965 opts.addMacroDef(
"PI=3.1415926535");
1969 opts.addMacroDef(
"ISPC_UINT_IS_DEFINED");
1972 char targetMacro[128];
1974 char *p = targetMacro;
1984 opts.addMacroDef(TARGET_WIDTH);
1987 std::string TARGET_ELEMENT_WIDTH =
"TARGET_ELEMENT_WIDTH=" + std::to_string(
g->
target->
getDataTypeWidth() / 8);
1988 opts.addMacroDef(TARGET_ELEMENT_WIDTH);
1990 opts.addMacroDef(targetMacro);
1993 opts.addMacroDef(
"ISPC_POINTER_SIZE=32");
1995 opts.addMacroDef(
"ISPC_POINTER_SIZE=64");
1998 opts.addMacroDef(
"ISPC_TARGET_HAS_HALF");
2000 opts.addMacroDef(
"ISPC_TARGET_HAS_RAND");
2002 opts.addMacroDef(
"ISPC_TARGET_HAS_TRANSCENDENTALS");
2004 opts.addMacroDef(
"ISPC_FORCE_ALIGNED_MEMORY");
2006 constexpr
int buf_size = 25;
2007 char ispc_major[buf_size], ispc_minor[buf_size];
2010 opts.addMacroDef(ispc_major);
2011 opts.addMacroDef(ispc_minor);
2015 opts.addMacroDef(
"assert(x)=");
2017 opts.addMacroDef(
"assert(x)=__assert(#x, x)");
2020 for (
unsigned int i = 0; i <
g->
cppArgs.size(); ++i) {
2022 if (
g->
cppArgs[i].substr(0, 2) ==
"-D") {
2023 opts.addMacroDef(
g->
cppArgs[i].substr(2));
2027 inst.getLangOpts().LineComment = 1;
2029 inst.createPreprocessor(clang::TU_Complete);
2031 diagPrinter->BeginSourceFile(inst.getLangOpts(), &inst.getPreprocessor());
2032 clang::DoPrintPreprocessedInput(inst.getPreprocessor(), ostream, inst.getPreprocessorOutputOpts());
2033 diagPrinter->EndSourceFile();
2040 int bufferSize = strlen(outFileName) + 16;
2041 char *targetOutFileName =
new char[bufferSize];
2042 if (strrchr(outFileName,
'.') != NULL) {
2044 int count = strrchr(outFileName,
'.') - outFileName;
2045 strncpy(targetOutFileName, outFileName, count);
2046 targetOutFileName[count] =
'\0';
2049 strncat(targetOutFileName,
"_", bufferSize - strlen(targetOutFileName) - 1);
2050 strncat(targetOutFileName, isaString, bufferSize - strlen(targetOutFileName) - 1);
2053 strncat(targetOutFileName, strrchr(outFileName,
'.'), bufferSize - strlen(targetOutFileName) - 1);
2057 strncpy(targetOutFileName, outFileName, bufferSize - 1);
2058 targetOutFileName[bufferSize - 1] =
'\0';
2059 strncat(targetOutFileName,
"_", bufferSize - strlen(targetOutFileName) - 1);
2060 strncat(targetOutFileName, isaString, bufferSize - strlen(targetOutFileName) - 1);
2062 return targetOutFileName;
2087 std::vector<Symbol *> syms;
2089 for (
unsigned int i = 0; i < syms.size(); ++i) {
2097 llvm::Type *ptrToInt8Ty = llvm::Type::getInt8PtrTy(*
g->
ctx);
2098 llvm::FunctionType *resultFuncTy = NULL;
2101 if (funcs.
func[i] == NULL) {
2104 bool foundVarying =
false;
2106 resultFuncTy = funcs.
func[i]->getFunctionType();
2109 llvm::SmallVector<llvm::Type *, 8> ftype;
2110 for (
int j = 0; j < numArgs; ++j) {
2111 ftype.push_back(resultFuncTy->getParamType(j));
2114 for (
int j = 0; j < numArgs; ++j) {
2118 const Type *baseType = CastType<PointerType>(arg)->GetBaseType();
2122 ftype[j] = ptrToInt8Ty;
2123 foundVarying =
true;
2128 resultFuncTy = llvm::FunctionType::get(resultFuncTy->getReturnType(), ftype,
false);
2137 return resultFuncTy;
2178 llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage, funcs.
func[i]->getName(),
module);
2180 targetFuncs[i] = NULL;
2183 bool voidReturn = ftype->getReturnType()->isVoidTy();
2186 llvm::Function *dispatchFunc =
2187 llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage, name.c_str(),
module);
2188 llvm::BasicBlock *bblock = llvm::BasicBlock::Create(*
g->
ctx,
"entry", dispatchFunc);
2192 llvm::CallInst::Create(setISAFunc,
"", bblock);
2195 llvm::Value *systemISA =
new llvm::LoadInst(systemBestISAPtr,
"system_isa", bblock);
2203 for (
int i = Target::NUM_ISAS - 1; i >= 0; --i) {
2204 if (targetFuncs[i] == NULL)
2211 llvm::Value *ok = llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_SGE, systemISA,
2213 llvm::BasicBlock *callBBlock = llvm::BasicBlock::Create(*
g->
ctx,
"do_call", dispatchFunc);
2214 llvm::BasicBlock *nextBBlock = llvm::BasicBlock::Create(*
g->
ctx,
"next_try", dispatchFunc);
2215 llvm::BranchInst::Create(callBBlock, nextBBlock, ok, bblock);
2220 std::vector<llvm::Value *> args;
2221 llvm::Function::arg_iterator argIter = dispatchFunc->arg_begin();
2222 llvm::Function::arg_iterator targsIter = targetFuncs[i]->arg_begin();
2223 for (; argIter != dispatchFunc->arg_end(); ++argIter, ++targsIter) {
2226 if (argIter->getType() == targsIter->getType()) {
2227 args.push_back(&*argIter);
2229 llvm::CastInst *argCast = llvm::CastInst::CreatePointerCast(&*argIter, targsIter->getType(),
2230 "dpatch_arg_bitcast", callBBlock);
2231 args.push_back(argCast);
2235 llvm::CallInst::Create(targetFuncs[i], args,
"", callBBlock);
2236 llvm::ReturnInst::Create(*
g->
ctx, callBBlock);
2238 llvm::Value *retValue = llvm::CallInst::Create(targetFuncs[i], args,
"ret_value", callBBlock);
2239 llvm::ReturnInst::Create(*
g->
ctx, retValue, callBBlock);
2244 bblock = nextBBlock;
2252 llvm::Function *abortFunc = module->getFunction(
"abort");
2254 llvm::CallInst::Create(abortFunc,
"", bblock);
2260 llvm::ReturnInst::Create(*
g->
ctx, bblock);
2262 llvm::Value *undefRet = llvm::UndefValue::get(ftype->getReturnType());
2263 llvm::ReturnInst::Create(*
g->
ctx, undefRet, bblock);
2269 llvm::Module *
module =
new llvm::Module(
"dispatch_module", *
g->
ctx);
2292 llvm::Function *setFunc = module->getFunction(
"__set_system_isa");
2294 llvm::Value *systemBestISAPtr = module->getGlobalVariable(
"__system_best_isa",
true);
2295 Assert(systemBestISAPtr != NULL);
2298 std::map<std::string, FunctionTargetVariants>::iterator iter;
2299 for (iter = functions.begin(); iter != functions.end(); ++iter)
2304 llvm::legacy::PassManager optPM;
2305 optPM.add(llvm::createGlobalDCEPass());
2306 optPM.add(llvm::createVerifierPass());
2312 while (Ty1->getTypeID() == Ty2->getTypeID())
2313 switch (Ty1->getTypeID()) {
2314 case llvm::ArrayType::ArrayTyID:
2315 if (Ty1->getArrayNumElements() != Ty2->getArrayNumElements())
2317 Ty1 = Ty1->getArrayElementType();
2318 Ty2 = Ty2->getArrayElementType();
2321 case llvm::ArrayType::PointerTyID:
2322 Ty1 = Ty1->getPointerElementType();
2323 Ty2 = Ty2->getPointerElementType();
2326 case llvm::ArrayType::StructTyID: {
2327 llvm::StructType *STy1 = llvm::dyn_cast<llvm::StructType>(Ty1);
2328 llvm::StructType *STy2 = llvm::dyn_cast<llvm::StructType>(Ty2);
2329 return STy1 && STy2 && STy1->isLayoutIdentical(STy2);
2344 llvm::Module::global_iterator iter;
2345 llvm::ValueToValueMapTy VMap;
2347 for (iter = msrc->global_begin(); iter != msrc->global_end(); ++iter) {
2348 llvm::GlobalVariable *gv = &*iter;
2350 if (gv->getLinkage() == llvm::GlobalValue::ExternalLinkage && gv->hasInitializer()) {
2351 llvm::Type *type = gv->getType()->getElementType();
2357 llvm::GlobalVariable *exist = mdst->getGlobalVariable(gv->getName());
2365 "Mismatch in size/layout of global " 2366 "variable \"%s\" with different targets. " 2367 "Globals must not include \"varying\" types or arrays " 2368 "with size based on programCount when compiling to " 2369 "targets with differing vector widths.",
2370 gv->getName().str().c_str());
2375 llvm::GlobalVariable *newGlobal =
2376 new llvm::GlobalVariable(*mdst, type, gv->isConstant(), llvm::GlobalValue::ExternalLinkage,
2377 (llvm::Constant *)
nullptr, gv->getName());
2378 VMap[&*iter] = newGlobal;
2380 newGlobal->setInitializer(llvm::MapValue(iter->getInitializer(), VMap));
2381 newGlobal->copyAttributesFrom(gv);
2385 gv->setInitializer(NULL);
2392 const char *headerFileName,
const char *includeFileName,
const char *depsFileName,
2393 const char *depsTargetName,
const char *hostStubFileName,
const char *devStubFileName) {
2394 if (targets.size() == 0 || targets.size() == 1) {
2398 if (targets.size() == 1) {
2399 target = targets[0];
2407 if (outputType ==
CXX) {
2409 Error(
SourcePos(),
"When generating C++ output, one of the \"generic-*\" " 2410 "targets must be used.");
2413 }
else if (outputType ==
Asm || outputType ==
Object) {
2416 "When using a \"generic-*\" compilation target, " 2417 "%s output can not be used.",
2418 (outputType ==
Asm) ?
"assembly" :
"object file");
2423 if (outFileName != NULL)
2424 if (!
m->
writeOutput(outputType, outputFlags, outFileName, includeFileName))
2426 if (headerFileName != NULL)
2430 std::string targetName;
2432 targetName = depsTargetName;
2433 else if (outFileName)
2434 targetName = outFileName;
2436 targetName = srcFile;
2437 size_t dot = targetName.find_last_of(
'.');
2438 if (dot != std::string::npos)
2439 targetName.erase(dot, std::string::npos);
2440 targetName.append(
".o");
2442 targetName =
"a.out";
2446 if (hostStubFileName != NULL)
2449 if (devStubFileName != NULL)
2462 return errorCount > 0;
2464 if (outputType ==
CXX) {
2465 Error(
SourcePos(),
"Illegal to specify more than one target when " 2466 "compiling C++ output.");
2470 Error(
SourcePos(),
"Compiling programs from standard input isn't " 2471 "supported when compiling for multiple targets. Please use " 2472 "an intermediate temporary file.");
2477 "for multiple targets.");
2482 Assert(targets.size() > 1);
2484 if (outFileName != NULL && strcmp(outFileName,
"-") == 0) {
2485 Error(
SourcePos(),
"Multi-target compilation can't generate output " 2486 "to stdout. Please provide an output filename.\n");
2496 targetMachines[i] = NULL;
2498 llvm::Module *dispatchModule = NULL;
2500 std::map<std::string, FunctionTargetVariants> exportedFunctions;
2506 if (headerFileName != NULL) {
2507 DHI.
file = fopen(headerFileName,
"w");
2512 DHI.
fn = headerFileName;
2523 for (
unsigned int i = 0; i < targets.size(); ++i) {
2533 "Can't compile to multiple variants of %s " 2544 bool check = (dispatchModule != NULL);
2554 if (outFileName != NULL) {
2555 std::string targetOutFileName;
2558 if (!
m->
writeOutput(outputType, outputFlags, targetOutFileName.c_str())) {
2567 if (errorCount != 0) {
2573 if (headerFileName != NULL) {
2574 if (i == targets.size() - 1) {
2579 const char *isaName;
2589 if (i == targets.size() - 1) {
2606 llvm::TargetMachine *firstTargetMachine = NULL;
2608 const char *firstISA =
"";
2610 while (i < Target::NUM_ISAS && firstTargetMachine == NULL) {
2613 firstTargetMachine = targetMachines[i++];
2615 Assert(strcmp(firstISA,
"") != 0);
2617 Assert(firstTargetMachine != NULL);
2624 if (dispatchModule == NULL) {
2631 if (outFileName != NULL) {
2639 std::string targetName;
2641 targetName = depsTargetName;
2642 else if (outFileName)
2643 targetName = outFileName;
2645 targetName = srcFile;
2646 size_t dot = targetName.find_last_of(
'.');
2647 if (dot != std::string::npos)
2648 targetName.erase(dot, std::string::npos);
2649 targetName.append(
".o");
2651 targetName =
"a.out";
2658 return errorCount > 0;
static const AtomicType * VaryingInt32
bool writeOutput(OutputType ot, OutputFlags flags, const char *filename, const char *includeFileName=NULL, const char *sourceFileName=NULL, DispatchHeaderInfo *DHI=0)
bool IsReferenceType() const
bool IsUniformType() const
llvm::Function * function
bool isMultiTargetCompilation
void DefineStdlib(SymbolTable *symbolTable, llvm::LLVMContext *ctx, llvm::Module *module, bool includeStdlibISPC)
llvm::DIFile * GetDIFile() const
void AddTypeDef(const std::string &name, const Type *type, SourcePos pos)
const Type * GetReturnType() const
virtual const Type * GetAsUnsignedType() const
std::vector< std::pair< const Type *, SourcePos > > exportedTypes
bool writeDevStub(const char *filename)
static void lEmitEnumDecls(const std::vector< const EnumType *> &enumTypes, FILE *file)
Declaration of the FunctionEmitContext class
#define ISPC_VERSION_MINOR
TargetLibRegistry * target_registry
bool AddFunction(Symbol *symbol)
static const AtomicType * VaryingUInt64
static void lCheckForStructParameters(const FunctionType *ftype, SourcePos pos)
YY_BUFFER_STATE yy_create_buffer(FILE *, int)
bool IsVaryingType() const
static llvm::Module * lInitDispatchModule()
static void lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc, llvm::Value *systemBestISAPtr, const std::string &name, FunctionTargetVariants &funcs)
#define UNESCAPE_SEQ(c, esc)
static void lExtractOrCheckGlobals(llvm::Module *msrc, llvm::Module *mdst, bool check)
static bool lSymbolIsExported(const Symbol *s)
Interface class for statements in the ispc language.
std::string emitOffloadParamStruct(const std::string ¶mStructName, const Symbol *sym, const FunctionType *fct)
Structure that defines a compilation target.
ASTNode * TypeCheck(ASTNode *root)
bool AddVariable(Symbol *symbol)
virtual std::pair< llvm::Constant *, bool > GetStorageConstant(const Type *type) const
static void lEmitVectorTypedefs(const std::vector< const VectorType *> &types, FILE *file)
const std::string & GetParameterName(int i) const
Expression representing a compile-time constant value.
llvm::Function * func[Target::NUM_ISAS]
Abstract base class for types that represent sequences.
std::vector< std::string > includePath
std::string GetCDeclaration(const std::string &fname) const
static void lCheckExportedParameterTypes(const Type *type, const std::string &name, SourcePos pos)
const Type * GetElementType() const
void AddFunctionDeclaration(const std::string &name, const FunctionType *ftype, StorageClass sc, bool isInline, bool isNoInline, SourcePos pos)
std::string Mangle() const
Symbol table that holds all known symbols during parsing and compilation.
std::string GetTripleString() const
void yy_switch_to_buffer(YY_BUFFER_STATE)
Expr * TypeConvertExpr(Expr *expr, const Type *toType, const char *errorMsgBase)
Declarations related to optimization passes.
void InitLLVMUtil(llvm::LLVMContext *ctx, Target &target)
static void lGetExportedTypes(const Type *type, std::vector< const StructType *> *exportedStructTypes, std::vector< const EnumType *> *exportedEnumTypes, std::vector< const VectorType *> *exportedVectorTypes)
const FunctionType * FTs[Target::NUM_ISAS]
int getDataTypeWidth() const
Declarations of functions related to builtins and the standard library.
int GetNumParameters() const
Symbol * LookupVariable(const char *name)
Type implementation for pointers to other types.
static bool lIsExternC(const Symbol *sym)
int TotalElementCount() const
bool writeHeader(const char *filename)
const Type * GetBaseType() const
static const StructType * lGetElementStructType(const Type *t)
bool writeObjectFileOrAssembly(OutputType outputType, const char *filename)
virtual llvm::Type * LLVMType(llvm::LLVMContext *ctx) const =0
header file with declarations for symbol and symbol table classes.
bool writeHostStub(const char *filename)
Type representing a reference to another (non-reference) type.
static llvm::FunctionType * lGetVaryingDispatchType(FunctionTargetVariants &funcs)
virtual const Type * GetReferenceTarget() const
virtual llvm::DIType * GetDIType(llvm::DIScope *scope) const =0
static bool lIsExported(const Symbol *sym)
void execPreprocessor(const char *infilename, llvm::raw_string_ostream *ostream) const
Expr * GetParameterDefault(int i) const
File with declarations for classes related to statements in the language.
struct yy_buffer_state * YY_BUFFER_STATE
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
std::set< std::string > registeredDependencies
const SourcePos & GetParameterSourcePos(int i) const
void RegisterDependency(const std::string &fileName)
static bool lContainsPtrToVarying(const StructType *st)
void AddExportedTypes(const std::vector< std::pair< const Type *, SourcePos >> &types)
bool AddType(const char *name, const Type *type, SourcePos pos)
bool LookupFunction(const char *name, std::vector< Symbol *> *matches=NULL)
static void lPrintFunctionDeclarations(FILE *file, const std::vector< Symbol *> &funcs, bool useExternC=1, bool rewriteForDispatch=false)
const Type * GetReferenceTarget() const
static void lGetExportedParamTypes(const std::vector< Symbol *> &funcs, std::vector< const StructType *> *exportedStructTypes, std::vector< const EnumType *> *exportedEnumTypes, std::vector< const VectorType *> *exportedVectorTypes)
static void lDeclareSizeAndPtrIntTypes(SymbolTable *symbolTable)
Representation of a structure holding a number of members.
int GetValues(bool *, bool forceVarying=false) const
char currentDirectory[1024]
void GetDirectoryAndFileName(const std::string ¤tDirectory, const std::string &relativeName, std::string *directory, std::string *filename)
bool mangleFunctionsWithTarget
Header file with declarations for various LLVM utility stuff.
const std::string & GetElementName(int i) const
ISPCTarget ParseISPCTarget(std::string target)
uint32_t RoundUpPow2(uint32_t v)
Module(const char *filename)
static void lGetExportedFunctions(SymbolTable *symbolTable, std::map< std::string, FunctionTargetVariants > &functions)
StorageClass storageClass
Representation of a range of positions in a source file.
bool generateDebuggingSymbols
llvm::ConstantInt * LLVMInt32(int32_t ival)
Type implementation for enumerated types.
virtual const Type * GetAsNonConstType() const =0
virtual std::string GetString() const =0
bool hasTranscendentals() const
bool force32BitAddressing
int GetElementCount() const
void markFuncWithTargetAttr(llvm::Function *func)
static void lEmitStructDecl(const StructType *st, std::vector< const StructType *> *emittedStructs, FILE *file, bool emitUnifs=true)
static const AtomicType * VaryingInt64
void Error(SourcePos p, const char *fmt,...)
#define ISPC_VERSION_MAJOR
int getVectorWidth() const
bool IsPointerType() const
static void lAddTypeIfNew(const Type *type, std::vector< const T *> *exportedTypes)
A (short) vector of atomic types.
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
const Type * GetElementType(const std::string &name) const
const llvm::DataLayout * getDataLayout() const
static void lEmitStructDecls(std::vector< const StructType *> &structTypes, FILE *file, bool emitUnifs=true)
const std::string GetCStructName() const
YY_BUFFER_STATE yy_scan_string(const char *)
Representation of a function in a source file.
static void lEmitDispatchModule(llvm::Module *module, std::map< std::string, FunctionTargetVariants > &functions)
std::string GetCDeclarationForDispatch(const std::string &fname) const
virtual const Type * GetElementType() const =0
static bool Equal(const Type *a, const Type *b)
static std::string lGetTargetFileName(const char *outFileName, const char *isaString)
void AddFunctionDefinition(const std::string &name, const FunctionType *ftype, Stmt *code)
const Type * GetParameterType(int i) const
const char * GetISAString() const
static void lUnescapeStringInPlace(std::string &str)
Type representing a function (return type + argument types)
Representation of a program symbol.
void AddFunction(Symbol *sym, Stmt *code)
virtual bool IsConstType() const =0
Interface class that defines the type abstraction.
Expr abstract base class and expression implementations.
void AddBitcodeToModule(const BitcodeLib *lib, llvm::Module *module, SymbolTable *symbolTable, bool warn)
llvm::DICompileUnit * diCompileUnit
static bool lRecursiveCheckValidParamType(const Type *t, bool vectorOk)
void GetMatchingFunctions(Predicate pred, std::vector< Symbol *> *matches) const
static bool lCompatibleTypes(llvm::Type *Ty1, llvm::Type *Ty2)
static bool writeBitcode(llvm::Module *module, const char *outFileName, OutputType outputType)
Expr is the abstract base class that defines the interface that all expression types must implement...
static void lStripUnusedDebugInfo(llvm::Module *module)
virtual std::string GetCDeclaration(const std::string &name) const =0
const BitcodeLib * getDispatchLib() const
ASTNode * Optimize(ASTNode *root)
bool writeDeps(const char *filename, bool generateMakeRule, const char *targetName=NULL, const char *srcFilename=NULL)
static const Type * SizeUnsizedArrays(const Type *type, Expr *initExpr)
virtual const Type * GetBaseType() const =0
static int CompileAndOutput(const char *srcFile, Arch arch, const char *cpu, std::vector< ISPCTarget > targets, OutputFlags outputFlags, OutputType outputType, const char *outFileName, const char *headerFileName, const char *includeFileName, const char *depsFileName, const char *depsTargetName, const char *hostStubFileName, const char *devStubFileName)
std::vector< std::string > cppArgs
void AddGlobalVariable(const std::string &name, const Type *type, Expr *initExpr, bool isConst, StorageClass storageClass, SourcePos pos)
int GetElementCount() const
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
const VectorType * GetAsNonConstType() const
virtual const Type * GetAsUnboundVariabilityType() const =0
void yy_delete_buffer(YY_BUFFER_STATE)
llvm::DIBuilder * diBuilder
void Warning(SourcePos p, const char *fmt,...)
static bool EqualIgnoringConst(const Type *a, const Type *b)
static const AtomicType * VaryingUInt32
static const char * ISAToTargetString(Target::ISA isa)
const std::string GetReturnTypeString() const
virtual llvm::Type * LLVMStorageType(llvm::LLVMContext *ctx) const
llvm::TargetMachine * GetTargetMachine() const
SymbolTable * symbolTable
llvm::Function * exportedFunction
bool IsStdin(const char *filepath)
File with declarations for classes related to type representation.
llvm::FunctionType * LLVMFunctionType(llvm::LLVMContext *ctx, bool disableMask=false) const
bool ISPCTargetIsGeneric(ISPCTarget target)
bool WriteCXXFile(llvm::Module *module, const char *fn, int vectorWidth, const char *includeName)
bool writeDispatchHeader(DispatchHeaderInfo *DHI)
One-dimensional array type.