diff --git a/builtins.cpp b/builtins.cpp index 1e908d31..bd714547 100644 --- a/builtins.cpp +++ b/builtins.cpp @@ -597,8 +597,14 @@ lSetInternalFunctions(llvm::Module *module) { int count = sizeof(names) / sizeof(names[0]); for (int i = 0; i < count; ++i) { llvm::Function *f = module->getFunction(names[i]); - if (f != NULL && f->empty() == false) + if (f != NULL && f->empty() == false) { f->setLinkage(llvm::GlobalValue::InternalLinkage); +#if !defined(LLVM_3_1) && !defined(LLVM_3_2) + f->addAttributes( + llvm::AttributeSet::FunctionIndex, + *g->target.tf_attributes); +#endif + } } } diff --git a/ispc.cpp b/ispc.cpp index b7737a42..3a602ce0 100644 --- a/ispc.cpp +++ b/ispc.cpp @@ -73,6 +73,7 @@ #include #else // LLVM 3.3+ #include + #include #endif #include #include @@ -419,6 +420,19 @@ Target::GetTarget(const char *arch, const char *cpu, const char *isa, const llvm::DataLayout *dataLayout = targetMachine->getDataLayout(); t->is32Bit = (dataLayout->getPointerSize(addressSpace) == 4); #endif + +#if !defined(LLVM_3_1) && !defined(LLVM_3_2) + // This is LLVM 3.3+ feature. + // Initialize target-specific "target-feature" attribute. + llvm::AttrBuilder attrBuilder; + attrBuilder.addAttribute("target-features", t->attributes); + t->tf_attributes = new llvm::AttributeSet( + llvm::AttributeSet::get( + *g->ctx, + llvm::AttributeSet::FunctionIndex, + attrBuilder)); +#endif + Assert(t->vectorWidth <= ISPC_MAX_NVEC); } diff --git a/ispc.h b/ispc.h index 66c3ee1c..1d456087 100644 --- a/ispc.h +++ b/ispc.h @@ -68,6 +68,7 @@ // Forward declarations of a number of widely-used LLVM types namespace llvm { + class AttributeSet; class BasicBlock; class Constant; class ConstantValue; @@ -224,9 +225,16 @@ struct Target { /** Target CPU. (e.g. "corei7", "corei7-avx", ..) */ std::string cpu; - /** Target-specific attributes to pass along to the LLVM backend */ + /** Target-specific attribute string to pass along to the LLVM backend */ std::string attributes; +#if !defined(LLVM_3_1) && !defined(LLVM_3_2) + /** Target-specific LLVM attribute, which has to be attached to every + function to ensure that it is generated for correct target architecture. + This is requirement was introduced in LLVM 3.3 */ + llvm::AttributeSet* tf_attributes; +#endif + /** Native vector width of the vector instruction set. Note that this value is directly derived from the ISA Being used (e.g. it's 4 for SSE, 8 for AVX, etc.) */ diff --git a/module.cpp b/module.cpp index 99aff4c0..f9477076 100644 --- a/module.cpp +++ b/module.cpp @@ -785,6 +785,10 @@ Module::AddFunctionDeclaration(const std::string &name, function->setDoesNotAlias(1); #endif +#if !defined(LLVM_3_1) && !defined(LLVM_3_2) + function->addAttributes(llvm::AttributeSet::FunctionIndex, *g->target.tf_attributes); +#endif + // Make sure that the return type isn't 'varying' or vector typed if // the function is 'export'ed. if (functionType->isExported && diff --git a/type.cpp b/type.cpp index a59101eb..d35baf05 100644 --- a/type.cpp +++ b/type.cpp @@ -2131,8 +2131,18 @@ StructType::GetDIType(llvm::DIDescriptor scope) const { llvm::DIArray elements = m->diBuilder->getOrCreateArray(elementLLVMTypes); llvm::DIFile diFile = pos.GetDIFile(); - return m->diBuilder->createStructType(scope, name, diFile, pos.first_line, currentSize, - align, 0, elements); + return m->diBuilder->createStructType( + scope, + name, + diFile, + pos.first_line, // Line number + currentSize, // Size in bits + align, // Alignment in bits + 0, // Flags +#if !defined(LLVM_3_1) && !defined(LLVM_3_2) + llvm::DIType(), // DerivedFrom +#endif + elements); } @@ -2364,9 +2374,18 @@ llvm::DIType UndefinedStructType::GetDIType(llvm::DIDescriptor scope) const { llvm::DIFile diFile = pos.GetDIFile(); llvm::DIArray elements; - return m->diBuilder->createStructType(scope, name, diFile, pos.first_line, - 0 /* size */, 0 /* align */, - 0 /* flags */, elements); + return m->diBuilder->createStructType( + scope, + name, + diFile, + pos.first_line, // Line number + 0, // Size + 0, // Align + 0, // Flags +#if !defined(LLVM_3_1) && !defined(LLVM_3_2) + llvm::DIType(), // DerivedFrom +#endif + elements); }