diff --git a/dmd/idgen.c b/dmd/idgen.c index 0e042e13..12d11463 100644 --- a/dmd/idgen.c +++ b/dmd/idgen.c @@ -230,6 +230,8 @@ Msgtable msgtable[] = { "no_moduleinfo" }, { "Alloca", "alloca" }, { "Shufflevector", "shufflevector" }, + { "Extractelement", "extractelement" }, + { "Insertelement", "insertelement" }, { "vastart", "va_start" }, { "vacopy", "va_copy" }, { "vaend", "va_end" }, diff --git a/dmd2/idgen.c b/dmd2/idgen.c index 457220bd..5334221f 100644 --- a/dmd2/idgen.c +++ b/dmd2/idgen.c @@ -274,6 +274,8 @@ Msgtable msgtable[] = { "no_moduleinfo" }, { "Alloca", "alloca" }, { "Shufflevector", "shufflevector" }, + { "Extractelement", "extractelement" }, + { "Insertelement", "insertelement" }, { "vastart", "va_start" }, { "vacopy", "va_copy" }, { "vaend", "va_end" }, diff --git a/gen/pragma.cpp b/gen/pragma.cpp index 2ac94850..4118d4d9 100644 --- a/gen/pragma.cpp +++ b/gen/pragma.cpp @@ -116,6 +116,17 @@ Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str) return LLVMshufflevector; } + // pragma(extractelement or insertelement) { funcdecl(s) } + else if (ident == Id::Extractelement || ident == Id::Insertelement) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return ident == Id::Extractelement ? LLVMextractelement : LLVMinsertelement; + } + // pragma(va_start) { templdecl(s) } else if (ident == Id::vastart) { @@ -375,6 +386,19 @@ void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s, } break; + case LLVMextractelement: + case LLVMinsertelement: + if (FuncDeclaration* fd = s->isFuncDeclaration()) + { + fd->llvmInternal = llvm_internal; + } + else + { + error("the '%s' pragma must only be used on function declarations.", ident->toChars()); + fatal(); + } + break; + case LLVMinline_asm: if (TemplateDeclaration* td = s->isTemplateDeclaration()) { diff --git a/gen/pragma.h b/gen/pragma.h index fc4322c1..9895bc2d 100644 --- a/gen/pragma.h +++ b/gen/pragma.h @@ -15,6 +15,8 @@ enum Pragma LLVMno_moduleinfo, LLVMalloca, LLVMshufflevector, + LLVMextractelement, + LLVMinsertelement, LLVMva_start, LLVMva_copy, LLVMva_end, diff --git a/gen/toir.cpp b/gen/toir.cpp index 3cde74cd..f819e36e 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -994,8 +994,8 @@ DValue* CallExp::toElem(IRState* p) llvm::SmallVector mask; for(int i = 2, n = arguments->dim; i < n; i++){ Expression* exp = static_cast(arguments->data[i]); - if(exp->op != TOKint64){ - error("Function %s was declared with pragma shufflevector. Because of that all of its arguments except the first two must be integer literals.", fndecl->toChars()); + if(exp->op != TOKint64 || exp->type->ty != Tint32){ + error("Function %s was declared with pragma shufflevector. Because of that all of its arguments except for the first two must be int literals.", fndecl->toChars()); fatal(); } IntegerExp* iexp = static_cast(arguments->data[i]); @@ -1007,7 +1007,33 @@ DValue* CallExp::toElem(IRState* p) LLValue* v1 = exp1->toElem(p)->getRVal(); LLValue* v2 = exp2->toElem(p)->getRVal(); return new DImValue(type, p->ir->CreateShuffleVector(v1, v2, maskVal)); - } + } + // extractelement + else if(fndecl->llvmInternal == LLVMextractelement) { + Expression* exp2 = static_cast(arguments->data[1]); + if(exp2->op != TOKint64 || exp2->type->ty != Tint32){ + error("Function %s was declared with pragma extractelement. Because of that its second argument must be an int literal.", fndecl->toChars()); + fatal(); + } + LLValue* idx = exp2->toElem(p)->getRVal(); + Expression* exp1 = static_cast(arguments->data[0]); + LLValue* vec = exp1->toElem(p)->getRVal(); + return new DImValue(type, p->ir->CreateExtractElement(vec, idx)); + } + // insertelement + else if(fndecl->llvmInternal == LLVMinsertelement) { + Expression* exp3 = static_cast(arguments->data[2]); + if(exp3->op != TOKint64 || exp3->type->ty != Tint32){ + error("Function %s was declared with pragma insertelement. Because of that its third argument must be an int literal.", fndecl->toChars()); + fatal(); + } + LLValue* idx = exp3->toElem(p)->getRVal(); + Expression* exp1 = static_cast(arguments->data[0]); + LLValue* vec = exp1->toElem(p)->getRVal(); + Expression* exp2 = static_cast(arguments->data[1]); + LLValue* scal = exp2->toElem(p)->getRVal(); + return new DImValue(type, p->ir->CreateInsertElement(vec, scal, idx)); + } // fence instruction else if (fndecl->llvmInternal == LLVMfence) { if (arguments->dim != 1) {