mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-17 04:13:13 +01:00
Implemented bt/btc/btr/bts intrinsics
This commit is contained in:
@@ -30,6 +30,18 @@ Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str)
|
||||
// pragma(intrinsic, "string") { funcdecl(s) }
|
||||
if (ident == Id::intrinsic)
|
||||
{
|
||||
struct LdcIntrinsic
|
||||
{
|
||||
std::string name;
|
||||
Pragma pragma;
|
||||
};
|
||||
static LdcIntrinsic ldcIntrinsic[] = {
|
||||
{ "bitop.bt", LLVMbitop_bt },
|
||||
{ "bitop.btc", LLVMbitop_btc },
|
||||
{ "bitop.btr", LLVMbitop_btr },
|
||||
{ "bitop.bts", LLVMbitop_bts },
|
||||
};
|
||||
|
||||
Expression* expr = (Expression *)args->data[0];
|
||||
expr = expr->semantic(sc);
|
||||
if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
|
||||
@@ -37,6 +49,27 @@ Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str)
|
||||
error("requires exactly 1 string literal parameter");
|
||||
fatal();
|
||||
}
|
||||
|
||||
std::string prefix = "ldc.";
|
||||
if (arg1str.length() > prefix.length() &&
|
||||
std::equal(prefix.begin(), prefix.end(), arg1str.begin()))
|
||||
{
|
||||
std::string name(arg1str.begin() + prefix.length(), arg1str.end());
|
||||
int i = 0, j = sizeof(ldcIntrinsic) / sizeof(ldcIntrinsic[0]), k, l;
|
||||
do
|
||||
{
|
||||
k = (i + j) / 2;
|
||||
l = name.compare(ldcIntrinsic[k].name);
|
||||
if (!l)
|
||||
return ldcIntrinsic[k].pragma;
|
||||
else if (l < 0)
|
||||
j = k;
|
||||
else
|
||||
i = k + 1;
|
||||
}
|
||||
while (i != j);
|
||||
}
|
||||
|
||||
return LLVMintrinsic;
|
||||
}
|
||||
|
||||
@@ -292,6 +325,10 @@ void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s,
|
||||
case LLVMva_copy:
|
||||
case LLVMva_end:
|
||||
case LLVMfence:
|
||||
case LLVMbitop_bt:
|
||||
case LLVMbitop_btc:
|
||||
case LLVMbitop_btr:
|
||||
case LLVMbitop_bts:
|
||||
if (FuncDeclaration* fd = s->isFuncDeclaration())
|
||||
{
|
||||
fd->llvmInternal = llvm_internal;
|
||||
|
||||
@@ -23,7 +23,11 @@ enum Pragma
|
||||
LLVMatomic_store,
|
||||
LLVMatomic_load,
|
||||
LLVMatomic_cmp_xchg,
|
||||
LLVMatomic_rmw
|
||||
LLVMatomic_rmw,
|
||||
LLVMbitop_bt,
|
||||
LLVMbitop_btc,
|
||||
LLVMbitop_btr,
|
||||
LLVMbitop_bts
|
||||
};
|
||||
|
||||
Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str);
|
||||
|
||||
52
gen/toir.cpp
52
gen/toir.cpp
@@ -1007,6 +1007,58 @@ DValue* CallExp::toElem(IRState* p)
|
||||
LLValue* ret = gIR->ir->CreateAtomicRMW(llvm::AtomicRMWInst::BinOp(op), ptr, val,
|
||||
llvm::AtomicOrdering(atomicOrdering));
|
||||
return new DImValue(exp2->type, ret);
|
||||
// bitop
|
||||
} else if (fndecl->llvmInternal == LLVMbitop_bt ||
|
||||
fndecl->llvmInternal == LLVMbitop_btr ||
|
||||
fndecl->llvmInternal == LLVMbitop_btc ||
|
||||
fndecl->llvmInternal == LLVMbitop_bts)
|
||||
{
|
||||
if (arguments->dim != 2) {
|
||||
error("bitop intrinsic %s expects 2 arguments");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Expression* exp1 = (Expression*)arguments->data[0];
|
||||
Expression* exp2 = (Expression*)arguments->data[1];
|
||||
LLValue* ptr = exp1->toElem(p)->getRVal();
|
||||
LLValue* bitnum = exp2->toElem(p)->getRVal();
|
||||
|
||||
// auto q = cast(ubyte*)ptr + (bitnum >> 3);
|
||||
LLValue* q = DtoBitCast(ptr, DtoType(Type::tuns8->pointerTo()));
|
||||
q = DtoGEP1(q, p->ir->CreateLShr(bitnum, 3), "bitop.q");
|
||||
|
||||
// auto mask = 1 << (bitnum & 7);
|
||||
LLValue* mask = p->ir->CreateAnd(bitnum, DtoConstSize_t(7), "bitop.tmp");
|
||||
mask = p->ir->CreateShl(DtoConstSize_t(1), mask, "bitop.mask");
|
||||
|
||||
// auto result = (*q & mask) ? -1 : 0;
|
||||
LLValue* val = p->ir->CreateZExt(DtoLoad(q, "bitop.tmp"), DtoSize_t(), "bitop.val");
|
||||
LLValue* result = p->ir->CreateAnd(val, mask, "bitop.tmp");
|
||||
result = p->ir->CreateICmpNE(result, DtoConstSize_t(0), "bitop.tmp");
|
||||
result = p->ir->CreateSelect(result, DtoConstInt(-1), DtoConstInt(0), "bitop.result");
|
||||
|
||||
if (fndecl->llvmInternal != LLVMbitop_bt) {
|
||||
llvm::Instruction::BinaryOps op;
|
||||
if (fndecl->llvmInternal == LLVMbitop_btc) {
|
||||
// *q ^= mask;
|
||||
op = llvm::Instruction::Xor;
|
||||
} else if (fndecl->llvmInternal == LLVMbitop_btr) {
|
||||
// *q &= ~mask;
|
||||
mask = p->ir->CreateNot(mask);
|
||||
op = llvm::Instruction::And;
|
||||
} else if (fndecl->llvmInternal == LLVMbitop_bts) {
|
||||
// *q |= mask;
|
||||
op = llvm::Instruction::Or;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
LLValue *newVal = p->ir->CreateBinOp(op, val, mask, "bitop.new_val");
|
||||
newVal = p->ir->CreateTrunc(newVal, DtoType(Type::tuns8), "bitop.tmp");
|
||||
DtoStore(newVal, q);
|
||||
}
|
||||
|
||||
return new DImValue(type, result);
|
||||
}
|
||||
}
|
||||
return DtoCallFunction(loc, type, fnval, arguments);
|
||||
|
||||
Submodule runtime/druntime updated: 4db79c70e9...3392500611
Reference in New Issue
Block a user