Intel SPMD Program Compiler  1.3.0
ispc.cpp
Go to the documentation of this file.
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 ispc.cpp
00035     @brief ispc global definitions
00036 */
00037 
00038 #include "ispc.h"
00039 #include "module.h"
00040 #include "util.h"
00041 #include "llvmutil.h"
00042 #include <stdio.h>
00043 #ifdef ISPC_IS_WINDOWS
00044 #include <windows.h>
00045 #include <direct.h>
00046 #define strcasecmp stricmp
00047 #endif
00048 #include <llvm/LLVMContext.h>
00049 #include <llvm/Module.h>
00050 #include <llvm/Analysis/DIBuilder.h>
00051 #if defined(LLVM_3_0) || defined(LLVM_3_1)
00052   #include <llvm/Analysis/DebugInfo.h>
00053 #else
00054   #include <llvm/DebugInfo.h>
00055 #endif
00056 #include <llvm/Support/Dwarf.h>
00057 #include <llvm/Instructions.h>
00058 #include <llvm/Target/TargetMachine.h>
00059 #include <llvm/Target/TargetOptions.h>
00060 #include <llvm/Target/TargetData.h>
00061 #include <llvm/Support/TargetRegistry.h>
00062 #include <llvm/Support/TargetSelect.h>
00063 #include <llvm/Support/Host.h>
00064 
00065 Globals *g;
00066 Module *m;
00067 
00068 ///////////////////////////////////////////////////////////////////////////
00069 // Target
00070 
00071 #ifndef ISPC_IS_WINDOWS
00072 static void __cpuid(int info[4], int infoType) {
00073     __asm__ __volatile__ ("cpuid"
00074                           : "=a" (info[0]), "=b" (info[1]), "=c" (info[2]), "=d" (info[3])
00075                           : "0" (infoType));
00076 }
00077 
00078 /* Save %ebx in case it's the PIC register */
00079 static void __cpuidex(int info[4], int level, int count) {
00080   __asm__ __volatile__ ("xchg{l}\t{%%}ebx, %1\n\t"
00081                         "cpuid\n\t"
00082                         "xchg{l}\t{%%}ebx, %1\n\t"
00083                         : "=a" (info[0]), "=r" (info[1]), "=c" (info[2]), "=d" (info[3])
00084                         : "0" (level), "2" (count));
00085 }
00086 #endif // ISPC_IS_WINDOWS
00087 
00088 
00089 static const char *
00090 lGetSystemISA() {
00091     int info[4];
00092     __cpuid(info, 1);
00093 
00094     if ((info[2] & (1 << 28)) != 0) {
00095         // AVX1 for sure. Do we have AVX2?
00096         // Call cpuid with eax=7, ecx=0
00097         __cpuidex(info, 7, 0);
00098         if ((info[1] & (1 << 5)) != 0)
00099             return "avx2";
00100         else {
00101             // ivybridge?
00102             if ((info[2] & (1 << 29)) != 0 &&  // F16C
00103                 (info[2] & (1 << 30)) != 0)    // RDRAND
00104                 return "avx1.1";
00105             else
00106                 return "avx";
00107         }
00108     }
00109     else if ((info[2] & (1 << 19)) != 0)
00110         return "sse4";
00111     else if ((info[3] & (1 << 26)) != 0)
00112         return "sse2";
00113     else {
00114         fprintf(stderr, "Unable to detect supported SSE/AVX ISA.  Exiting.\n");
00115         exit(1);
00116     }
00117 }
00118 
00119 
00120 static const char *supportedCPUs[] = { 
00121     "atom", "penryn", "core2", "corei7", "corei7-avx"
00122 };
00123 
00124 
00125 bool
00126 Target::GetTarget(const char *arch, const char *cpu, const char *isa,
00127                   bool pic, Target *t) {
00128     if (isa == NULL) {
00129         if (cpu != NULL) {
00130             // If a CPU was specified explicitly, try to pick the best
00131             // possible ISA based on that.
00132             if (!strcmp(cpu, "sandybridge") ||
00133                 !strcmp(cpu, "corei7-avx"))
00134                 isa = "avx";
00135             else if (!strcmp(cpu, "corei7") ||
00136                      !strcmp(cpu, "penryn"))
00137                 isa = "sse4";
00138             else
00139                 isa = "sse2";
00140             fprintf(stderr, "Notice: no --target specified on command-line.  "
00141                     "Using ISA \"%s\" based on specified CPU \"%s\".\n", isa,
00142                     cpu);
00143         }
00144         else {
00145             // No CPU and no ISA, so use CPUID to figure out what this CPU
00146             // supports.
00147             isa = lGetSystemISA();
00148             fprintf(stderr, "Notice: no --target specified on command-line.  "
00149                     "Using system ISA \"%s\".\n", isa);
00150         }
00151     }
00152 
00153     if (cpu == NULL) {
00154         std::string hostCPU = llvm::sys::getHostCPUName();
00155         if (hostCPU.size() > 0)
00156             cpu = strdup(hostCPU.c_str());
00157         else {
00158             fprintf(stderr, "Warning: unable to determine host CPU!\n");
00159             cpu = "generic";
00160         }
00161     }
00162     else {
00163         bool foundCPU = false;
00164         for (int i = 0; i < int(sizeof(supportedCPUs) / sizeof(supportedCPUs[0])); 
00165              ++i) {
00166             if (!strcmp(cpu, supportedCPUs[i])) {
00167                 foundCPU = true;
00168                 break;
00169             }
00170         }
00171         if (foundCPU == false) {
00172             fprintf(stderr, "Error: CPU type \"%s\" unknown. Supported CPUs: "
00173                     "%s.\n", cpu, SupportedTargetCPUs().c_str());
00174             return false;
00175         }
00176     }
00177 
00178     t->cpu = cpu;
00179 
00180     if (arch == NULL)
00181         arch = "x86-64";
00182 
00183     bool error = false;
00184 
00185     t->generatePIC = pic;
00186 
00187     // Make sure the target architecture is a known one; print an error
00188     // with the valid ones otherwise.
00189     t->target = NULL;
00190     for (llvm::TargetRegistry::iterator iter = llvm::TargetRegistry::begin();
00191          iter != llvm::TargetRegistry::end(); ++iter) {
00192         if (std::string(arch) == iter->getName()) {
00193             t->target = &*iter;
00194             break;
00195         }
00196     }
00197     if (t->target == NULL) {
00198         fprintf(stderr, "Invalid architecture \"%s\"\nOptions: ", arch);
00199         llvm::TargetRegistry::iterator iter;
00200         for (iter = llvm::TargetRegistry::begin();
00201              iter != llvm::TargetRegistry::end(); ++iter)
00202             fprintf(stderr, "%s ", iter->getName());
00203         fprintf(stderr, "\n");
00204         error = true;
00205     }
00206     else {
00207         t->arch = arch;
00208     }
00209 
00210     // This is the case for most of them
00211     t->hasHalf = t->hasRand = t->hasTranscendentals = false;
00212 
00213     if (!strcasecmp(isa, "sse2")) {
00214         t->isa = Target::SSE2;
00215         t->nativeVectorWidth = 4;
00216         t->vectorWidth = 4;
00217         t->attributes = "+sse,+sse2,-sse3,-sse41,-sse42,-sse4a,-ssse3,-popcnt";
00218         t->maskingIsFree = false;
00219         t->maskBitCount = 32;
00220     }
00221     else if (!strcasecmp(isa, "sse2-x2")) {
00222         t->isa = Target::SSE2;
00223         t->nativeVectorWidth = 4;
00224         t->vectorWidth = 8;
00225         t->attributes = "+sse,+sse2,-sse3,-sse41,-sse42,-sse4a,-ssse3,-popcnt";
00226         t->maskingIsFree = false;
00227         t->maskBitCount = 32;
00228     }
00229     else if (!strcasecmp(isa, "sse4")) {
00230         t->isa = Target::SSE4;
00231         t->nativeVectorWidth = 4;
00232         t->vectorWidth = 4;
00233         t->attributes = "+sse,+sse2,+sse3,+sse41,-sse42,-sse4a,+ssse3,-popcnt,+cmov";
00234         t->maskingIsFree = false;
00235         t->maskBitCount = 32;
00236     }
00237     else if (!strcasecmp(isa, "sse4x2") || !strcasecmp(isa, "sse4-x2")) {
00238         t->isa = Target::SSE4;
00239         t->nativeVectorWidth = 4;
00240         t->vectorWidth = 8;
00241         t->attributes = "+sse,+sse2,+sse3,+sse41,-sse42,-sse4a,+ssse3,-popcnt,+cmov";
00242         t->maskingIsFree = false;
00243         t->maskBitCount = 32;
00244     }
00245     else if (!strcasecmp(isa, "generic-4")) {
00246         t->isa = Target::GENERIC;
00247         t->nativeVectorWidth = 4;
00248         t->vectorWidth = 4;
00249         t->maskingIsFree = true;
00250         t->maskBitCount = 1;
00251         t->hasHalf = true;
00252         t->hasTranscendentals = true;
00253     }
00254     else if (!strcasecmp(isa, "generic-8")) {
00255         t->isa = Target::GENERIC;
00256         t->nativeVectorWidth = 8;
00257         t->vectorWidth = 8;
00258         t->maskingIsFree = true;
00259         t->maskBitCount = 1;
00260         t->hasHalf = true;
00261         t->hasTranscendentals = true;
00262     }
00263     else if (!strcasecmp(isa, "generic-16")) {
00264         t->isa = Target::GENERIC;
00265         t->nativeVectorWidth = 16;
00266         t->vectorWidth = 16;
00267         t->maskingIsFree = true;
00268         t->maskBitCount = 1;
00269         t->hasHalf = true;
00270         t->hasTranscendentals = true;
00271     }
00272     else if (!strcasecmp(isa, "generic-32")) {
00273         t->isa = Target::GENERIC;
00274         t->nativeVectorWidth = 32;
00275         t->vectorWidth = 32;
00276         t->maskingIsFree = true;
00277         t->maskBitCount = 1;
00278         t->hasHalf = true;
00279         t->hasTranscendentals = true;
00280     }
00281     else if (!strcasecmp(isa, "generic-64")) {
00282         t->isa = Target::GENERIC;
00283         t->nativeVectorWidth = 64;
00284         t->vectorWidth = 64;
00285         t->maskingIsFree = true;
00286         t->maskBitCount = 1;
00287         t->hasHalf = true;
00288         t->hasTranscendentals = true;
00289     }
00290     else if (!strcasecmp(isa, "generic-1")) {
00291         t->isa = Target::GENERIC;
00292         t->nativeVectorWidth = 1;
00293         t->vectorWidth = 1;
00294         t->maskingIsFree = false;
00295         t->maskBitCount = 32;
00296     }
00297     else if (!strcasecmp(isa, "avx") || !strcasecmp(isa, "avx1")) {
00298         t->isa = Target::AVX;
00299         t->nativeVectorWidth = 8;
00300         t->vectorWidth = 8;
00301         t->attributes = "+avx,+popcnt,+cmov";
00302         t->maskingIsFree = false;
00303         t->maskBitCount = 32;
00304     }
00305     else if (!strcasecmp(isa, "avx-x2") || !strcasecmp(isa, "avx1-x2")) {
00306         t->isa = Target::AVX;
00307         t->nativeVectorWidth = 8;
00308         t->vectorWidth = 16;
00309         t->attributes = "+avx,+popcnt,+cmov";
00310         t->maskingIsFree = false;
00311         t->maskBitCount = 32;
00312     }
00313     else if (!strcasecmp(isa, "avx1.1")) {
00314         t->isa = Target::AVX11;
00315         t->nativeVectorWidth = 8;
00316         t->vectorWidth = 8;
00317         t->attributes = "+avx,+popcnt,+cmov,+f16c,+rdrand";
00318         t->maskingIsFree = false;
00319         t->maskBitCount = 32;
00320         t->hasHalf = true;
00321         t->hasRand = true;
00322     }
00323     else if (!strcasecmp(isa, "avx1.1-x2")) {
00324         t->isa = Target::AVX11;
00325         t->nativeVectorWidth = 8;
00326         t->vectorWidth = 16;
00327         t->attributes = "+avx,+popcnt,+cmov,+f16c,+rdrand";
00328         t->maskingIsFree = false;
00329         t->maskBitCount = 32;
00330         t->hasHalf = true;
00331         t->hasRand = true;
00332     }
00333 #ifndef LLVM_3_0
00334     else if (!strcasecmp(isa, "avx2")) {
00335         t->isa = Target::AVX2;
00336         t->nativeVectorWidth = 8;
00337         t->vectorWidth = 8;
00338         t->attributes = "+avx2,+popcnt,+cmov,+f16c,+rdrand";
00339         t->maskingIsFree = false;
00340         t->maskBitCount = 32;
00341         t->hasHalf = true;
00342         t->hasRand = true;
00343     }
00344     else if (!strcasecmp(isa, "avx2-x2")) {
00345         t->isa = Target::AVX2;
00346         t->nativeVectorWidth = 16;
00347         t->vectorWidth = 16;
00348         t->attributes = "+avx2,+popcnt,+cmov,+f16c,+rdrand";
00349         t->maskingIsFree = false;
00350         t->maskBitCount = 32;
00351         t->hasHalf = true;
00352         t->hasRand = true;
00353     }
00354 #endif // !LLVM_3_0
00355     else {
00356         fprintf(stderr, "Target ISA \"%s\" is unknown.  Choices are: %s\n", 
00357                 isa, SupportedTargetISAs());
00358         error = true;
00359     }
00360 
00361     if (!error) {
00362         llvm::TargetMachine *targetMachine = t->GetTargetMachine();
00363         const llvm::TargetData *targetData = targetMachine->getTargetData();
00364         t->is32Bit = (targetData->getPointerSize() == 4);
00365         Assert(t->vectorWidth <= ISPC_MAX_NVEC);
00366     }
00367 
00368     return !error;
00369 }
00370 
00371 
00372 std::string
00373 Target::SupportedTargetCPUs() {
00374     std::string ret;
00375     int count = sizeof(supportedCPUs) / sizeof(supportedCPUs[0]);
00376     for (int i = 0; i < count; ++i) {
00377         ret += supportedCPUs[i];
00378         if (i != count - 1)
00379             ret += ", ";
00380     }
00381     return ret;
00382 }
00383 
00384 
00385 const char *
00386 Target::SupportedTargetArchs() {
00387     return "x86, x86-64";
00388 }
00389 
00390 
00391 const char *
00392 Target::SupportedTargetISAs() {
00393     return "sse2, sse2-x2, sse4, sse4-x2, avx, avx-x2"
00394 #ifndef LLVM_3_0
00395         ", avx1.1, avx1.1-x2, avx2, avx2-x2"
00396 #endif // !LLVM_3_0
00397         ", generic-1, generic-4, generic-8, generic-16, generic-32";
00398 }
00399 
00400 
00401 std::string
00402 Target::GetTripleString() const {
00403     llvm::Triple triple;
00404     // Start with the host triple as the default
00405 #ifdef LLVM_3_0
00406     triple.setTriple(llvm::sys::getHostTriple());
00407 #else
00408     triple.setTriple(llvm::sys::getDefaultTargetTriple());
00409 #endif
00410 
00411     // And override the arch in the host triple based on what the user
00412     // specified.  Here we need to deal with the fact that LLVM uses one
00413     // naming convention for targets TargetRegistry, but wants some
00414     // slightly different ones for the triple.  TODO: is there a way to
00415     // have it do this remapping, which would presumably be a bit less
00416     // error prone?
00417     if (arch == "x86")
00418         triple.setArchName("i386");
00419     else if (arch == "x86-64")
00420         triple.setArchName("x86_64");
00421     else
00422         triple.setArchName(arch);
00423 
00424     return triple.str();
00425 }
00426 
00427 
00428 llvm::TargetMachine *
00429 Target::GetTargetMachine() const {
00430     std::string triple = GetTripleString();
00431 
00432     llvm::Reloc::Model relocModel = generatePIC ? llvm::Reloc::PIC_ : 
00433                                                   llvm::Reloc::Default;
00434 #ifdef LLVM_3_0
00435     std::string featuresString = attributes;
00436     llvm::TargetMachine *targetMachine = 
00437         target->createTargetMachine(triple, cpu, featuresString, relocModel);
00438 #else
00439     std::string featuresString = attributes;
00440     llvm::TargetOptions options;
00441     llvm::TargetMachine *targetMachine = 
00442         target->createTargetMachine(triple, cpu, featuresString, options,
00443                                     relocModel);
00444 #endif // !LLVM_3_0
00445     Assert(targetMachine != NULL);
00446 
00447     targetMachine->setAsmVerbosityDefault(true);
00448     return targetMachine;
00449 }
00450 
00451 
00452 const char *
00453 Target::GetISAString() const {
00454     switch (isa) {
00455     case Target::SSE2:
00456         return "sse2";
00457     case Target::SSE4:
00458         return "sse4";
00459     case Target::AVX:
00460         return "avx";
00461     case Target::AVX11:
00462         return "avx11";
00463     case Target::AVX2:
00464         return "avx2";
00465     case Target::GENERIC:
00466         return "generic";
00467     default:
00468         FATAL("Unhandled target in GetISAString()");
00469     }
00470     return "";
00471 }
00472 
00473 
00474 static bool
00475 lGenericTypeLayoutIndeterminate(llvm::Type *type) {
00476     if (type->isPrimitiveType() || type->isIntegerTy())
00477         return false;
00478 
00479     if (type == LLVMTypes::BoolVectorType ||
00480         type == LLVMTypes::MaskType ||
00481         type == LLVMTypes::Int1VectorType)
00482         return true;
00483 
00484     llvm::ArrayType *at = 
00485         llvm::dyn_cast<llvm::ArrayType>(type);
00486     if (at != NULL)
00487         return lGenericTypeLayoutIndeterminate(at->getElementType());
00488 
00489     llvm::PointerType *pt = 
00490         llvm::dyn_cast<llvm::PointerType>(type);
00491     if (pt != NULL)
00492         return false;
00493 
00494     llvm::StructType *st =
00495         llvm::dyn_cast<llvm::StructType>(type);
00496     if (st != NULL) {
00497         for (int i = 0; i < (int)st->getNumElements(); ++i)
00498             if (lGenericTypeLayoutIndeterminate(st->getElementType(i)))
00499                 return true;
00500         return false;
00501     }
00502 
00503     Assert(llvm::isa<llvm::VectorType>(type));
00504     return true;
00505 }
00506 
00507 
00508 llvm::Value *
00509 Target::SizeOf(llvm::Type *type, 
00510                llvm::BasicBlock *insertAtEnd) {
00511     if (isa == Target::GENERIC &&
00512         lGenericTypeLayoutIndeterminate(type)) {
00513         llvm::Value *index[1] = { LLVMInt32(1) };
00514         llvm::PointerType *ptrType = llvm::PointerType::get(type, 0);
00515         llvm::Value *voidPtr = llvm::ConstantPointerNull::get(ptrType);
00516         llvm::ArrayRef<llvm::Value *> arrayRef(&index[0], &index[1]);
00517         llvm::Instruction *gep = 
00518             llvm::GetElementPtrInst::Create(voidPtr, arrayRef, "sizeof_gep",
00519                                             insertAtEnd);
00520 
00521         if (is32Bit || g->opt.force32BitAddressing)
00522             return new llvm::PtrToIntInst(gep, LLVMTypes::Int32Type, 
00523                                           "sizeof_int", insertAtEnd);
00524         else
00525             return new llvm::PtrToIntInst(gep, LLVMTypes::Int64Type, 
00526                                           "sizeof_int", insertAtEnd);
00527     }
00528 
00529     const llvm::TargetData *td = GetTargetMachine()->getTargetData();
00530     Assert(td != NULL);
00531     uint64_t bitSize = td->getTypeSizeInBits(type);
00532     Assert((bitSize % 8) == 0);
00533     uint64_t byteSize = bitSize / 8;
00534     if (is32Bit || g->opt.force32BitAddressing)
00535         return LLVMInt32((int32_t)byteSize);
00536     else
00537         return LLVMInt64(byteSize);
00538 }
00539 
00540 
00541 llvm::Value *
00542 Target::StructOffset(llvm::Type *type, int element,
00543                      llvm::BasicBlock *insertAtEnd) {
00544     if (isa == Target::GENERIC && 
00545         lGenericTypeLayoutIndeterminate(type) == true) {
00546         llvm::Value *indices[2] = { LLVMInt32(0), LLVMInt32(element) };
00547         llvm::PointerType *ptrType = llvm::PointerType::get(type, 0);
00548         llvm::Value *voidPtr = llvm::ConstantPointerNull::get(ptrType);
00549         llvm::ArrayRef<llvm::Value *> arrayRef(&indices[0], &indices[2]);
00550         llvm::Instruction *gep = 
00551             llvm::GetElementPtrInst::Create(voidPtr, arrayRef, "offset_gep",
00552                                             insertAtEnd);
00553 
00554         if (is32Bit || g->opt.force32BitAddressing)
00555             return new llvm::PtrToIntInst(gep, LLVMTypes::Int32Type, 
00556                                           "offset_int", insertAtEnd);
00557         else
00558             return new llvm::PtrToIntInst(gep, LLVMTypes::Int64Type, 
00559                                           "offset_int", insertAtEnd);
00560     }
00561 
00562     const llvm::TargetData *td = GetTargetMachine()->getTargetData();
00563     Assert(td != NULL);
00564     llvm::StructType *structType = 
00565         llvm::dyn_cast<llvm::StructType>(type);
00566     if (structType == NULL || structType->isSized() == false) {
00567         Assert(m->errorCount > 0);
00568         return NULL;
00569     }
00570     const llvm::StructLayout *sl = td->getStructLayout(structType);
00571     Assert(sl != NULL);
00572 
00573     uint64_t offset = sl->getElementOffset(element);
00574     if (is32Bit || g->opt.force32BitAddressing)
00575         return LLVMInt32((int32_t)offset);
00576     else
00577         return LLVMInt64(offset);
00578 }
00579 
00580 
00581 ///////////////////////////////////////////////////////////////////////////
00582 // Opt
00583 
00584 Opt::Opt() {
00585     level = 1;
00586     fastMath = false;
00587     fastMaskedVload = false;
00588     force32BitAddressing = true;
00589     unrollLoops = true;
00590     disableAsserts = false;
00591     disableMaskAllOnOptimizations = false;
00592     disableHandlePseudoMemoryOps = false;
00593     disableBlendedMaskedStores = false;
00594     disableCoherentControlFlow = false;
00595     disableUniformControlFlow = false;
00596     disableGatherScatterOptimizations = false;
00597     disableMaskedStoreToStore = false;
00598     disableGatherScatterFlattening = false;
00599     disableUniformMemoryOptimizations = false;
00600     disableCoalescing = false;
00601 }
00602 
00603 ///////////////////////////////////////////////////////////////////////////
00604 // Globals
00605 
00606 Globals::Globals() {
00607     mathLib = Globals::Math_ISPC;
00608 
00609     includeStdlib = true;
00610     runCPP = true;
00611     debugPrint = false;
00612     disableWarnings = false;
00613     warningsAsErrors = false;
00614     quiet = false;
00615     forceColoredOutput = false;
00616     disableLineWrap = false;
00617     emitPerfWarnings = true;
00618     emitInstrumentation = false;
00619     generateDebuggingSymbols = false;
00620     enableFuzzTest = false;
00621     fuzzTestSeed = -1;
00622     mangleFunctionsWithTarget = false;
00623     
00624     ctx = new llvm::LLVMContext;
00625 
00626 #ifdef ISPC_IS_WINDOWS
00627     _getcwd(currentDirectory, sizeof(currentDirectory));
00628 #else
00629     if (getcwd(currentDirectory, sizeof(currentDirectory)) == NULL)
00630         FATAL("Current directory path too long!");
00631 #endif
00632 }
00633 
00634 ///////////////////////////////////////////////////////////////////////////
00635 // SourcePos
00636 
00637 SourcePos::SourcePos(const char *n, int fl, int fc, int ll, int lc) {
00638     name = n;
00639     if (name == NULL) {
00640         if (m != NULL)
00641             name = m->module->getModuleIdentifier().c_str();
00642         else
00643             name = "(unknown)";
00644     }
00645     first_line = fl;
00646     first_column = fc;
00647     last_line = ll != 0 ? ll : fl;
00648     last_column = lc != 0 ? lc : fc;
00649 }
00650 
00651 
00652 llvm::DIFile
00653 SourcePos::GetDIFile() const {
00654     std::string directory, filename;
00655     GetDirectoryAndFileName(g->currentDirectory, name, &directory, &filename);
00656     llvm::DIFile ret = m->diBuilder->createFile(filename, directory);
00657     Assert(ret.Verify());
00658     return ret;
00659 }
00660 
00661 
00662 void
00663 SourcePos::Print() const { 
00664     printf(" @ [%s:%d.%d - %d.%d] ", name, first_line, first_column,
00665            last_line, last_column); 
00666 }
00667 
00668 
00669 bool
00670 SourcePos::operator==(const SourcePos &p2) const {
00671     return (!strcmp(name, p2.name) && 
00672             first_line == p2.first_line &&
00673             first_column == p2.first_column &&
00674             last_line == p2.last_line &&
00675             last_column == p2.last_column);
00676 }
00677 
00678 
00679 SourcePos
00680 Union(const SourcePos &p1, const SourcePos &p2) {
00681     if (strcmp(p1.name, p2.name) != 0)
00682         return p1;
00683 
00684     SourcePos ret;
00685     ret.name = p1.name;
00686     ret.first_line = std::min(p1.first_line, p2.first_line);
00687     ret.first_column = std::min(p1.first_column, p2.first_column);
00688     ret.last_line = std::max(p1.last_line, p2.last_line);
00689     ret.last_column = std::max(p1.last_column, p2.last_column);
00690     return ret;
00691 }