diff --git a/dmd2/idgen.c b/dmd2/idgen.c index 96899737..5334221f 100644 --- a/dmd2/idgen.c +++ b/dmd2/idgen.c @@ -275,6 +275,7 @@ Msgtable msgtable[] = { "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 0ef0b324..588b6568 100644 --- a/gen/pragma.cpp +++ b/gen/pragma.cpp @@ -127,6 +127,17 @@ Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str) return LLVMextractelement; } + // pragma(insertelement) { funcdecl(s) } + else if (ident == Id::Insertelement) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMinsertelement; + } + // pragma(va_start) { templdecl(s) } else if (ident == Id::vastart) { @@ -398,6 +409,18 @@ void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s, } break; + 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 6da358c0..9895bc2d 100644 --- a/gen/pragma.h +++ b/gen/pragma.h @@ -16,6 +16,7 @@ enum Pragma LLVMalloca, LLVMshufflevector, LLVMextractelement, + LLVMinsertelement, LLVMva_start, LLVMva_copy, LLVMva_end, diff --git a/gen/toir.cpp b/gen/toir.cpp index 474d8004..d9bfdcfd 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1015,11 +1015,25 @@ DValue* CallExp::toElem(IRState* p) error("Function %s was declared with pragma extractelement. Because of that its second argument must be an integer literal.", fndecl->toChars()); fatal(); } - LLConstant* idx = static_cast(arguments->data[1])->toConstElem(p); + 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){ + error("Function %s was declared with pragma extractelement. Because of that its second argument must be an integer 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) {