mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-29 14:40:40 +03:00
Adapt to new string-switch lowering
Now all done in the front-end, no need for us to handle it manually anymore. This also fixes tests/semantic/dcompute.d.
This commit is contained in:
parent
a4005d80a0
commit
b83780538f
4 changed files with 18 additions and 114 deletions
1
dmd/id.h
1
dmd/id.h
|
@ -33,6 +33,7 @@ public:
|
|||
static Identifier *__c_long;
|
||||
static Identifier *__c_ulong;
|
||||
static Identifier *__c_long_double;
|
||||
static Identifier *__switch;
|
||||
static Identifier *lib;
|
||||
static Identifier *ldc;
|
||||
static Identifier *dcompute;
|
||||
|
|
|
@ -664,22 +664,6 @@ static void buildRuntimeModule() {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// int _d_switch_string(char[][] table, char[] ca)
|
||||
createFwdDecl(LINKc, intTy, {"_d_switch_string"},
|
||||
{stringTy->arrayOf(), stringTy}, {}, Attr_ReadOnly);
|
||||
|
||||
// int _d_switch_ustring(wchar[][] table, wchar[] ca)
|
||||
createFwdDecl(LINKc, intTy, {"_d_switch_ustring"},
|
||||
{wstringTy->arrayOf(), wstringTy}, {}, Attr_ReadOnly);
|
||||
|
||||
// int _d_switch_dstring(dchar[][] table, dchar[] ca)
|
||||
createFwdDecl(LINKc, intTy, {"_d_switch_dstring"},
|
||||
{dstringTy->arrayOf(), dstringTy}, {}, Attr_ReadOnly);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// int _d_eh_personality(...)
|
||||
{
|
||||
if (global.params.targetTriple->isWindowsMSVCEnvironment()) {
|
||||
|
|
|
@ -169,7 +169,8 @@ struct DComputeSemanticAnalyser : public StoppableVisitor {
|
|||
stop = true;
|
||||
}
|
||||
void visit(SwitchStatement *e) override {
|
||||
if (!e->condition->type->isintegral()) {
|
||||
if (e->condition->op == TOKcall &&
|
||||
static_cast<CallExp *>(e->condition)->f->ident == Id::__switch) {
|
||||
e->error("cannot `switch` on strings in `@compute` code");
|
||||
stop = true;
|
||||
}
|
||||
|
|
|
@ -45,47 +45,6 @@ void CompoundAsmStatement_toIR(CompoundAsmStatement *stmt, IRState *p);
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For sorting string switch cases lexicographically.
|
||||
namespace {
|
||||
bool compareCaseStrings(CaseStatement *lhs, CaseStatement *rhs) {
|
||||
return lhs->exp->compare(rhs->exp) < 0;
|
||||
}
|
||||
}
|
||||
|
||||
static LLValue *call_string_switch_runtime(llvm::Value *table, Expression *e) {
|
||||
Type *dt = e->type->toBasetype();
|
||||
Type *dtnext = dt->nextOf()->toBasetype();
|
||||
TY ty = dtnext->ty;
|
||||
const char *fname;
|
||||
if (ty == Tchar) {
|
||||
fname = "_d_switch_string";
|
||||
} else if (ty == Twchar) {
|
||||
fname = "_d_switch_ustring";
|
||||
} else if (ty == Tdchar) {
|
||||
fname = "_d_switch_dstring";
|
||||
} else {
|
||||
llvm_unreachable("not char/wchar/dchar");
|
||||
}
|
||||
|
||||
llvm::Function *fn = getRuntimeFunction(e->loc, gIR->module, fname);
|
||||
|
||||
IF_LOG {
|
||||
Logger::cout() << *table->getType() << '\n';
|
||||
Logger::cout() << *fn->getFunctionType()->getParamType(0) << '\n';
|
||||
}
|
||||
assert(table->getType() == fn->getFunctionType()->getParamType(0));
|
||||
|
||||
DValue *val = toElemDtor(e);
|
||||
LLValue *llval = DtoRVal(val);
|
||||
assert(llval->getType() == fn->getFunctionType()->getParamType(1));
|
||||
|
||||
LLCallSite call = gIR->CreateCallOrInvoke(fn, table, llval);
|
||||
|
||||
return call.getInstruction();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ToIRVisitor : public Visitor {
|
||||
IRState *irs;
|
||||
|
||||
|
@ -893,9 +852,7 @@ public:
|
|||
emitCoverageLinecountInc(stmt->loc);
|
||||
llvm::BasicBlock *const oldbb = irs->scopebb();
|
||||
|
||||
// The cases of the switch statement, in codegen order. For string switches,
|
||||
// we reorder them lexicographically later to match what the _d_switch_*
|
||||
// druntime dispatch functions expect.
|
||||
// The cases of the switch statement, in codegen order.
|
||||
auto cases = stmt->cases;
|
||||
const auto caseCount = cases->dim;
|
||||
|
||||
|
@ -906,56 +863,22 @@ public:
|
|||
indices.reserve(caseCount);
|
||||
bool useSwitchInst = true;
|
||||
|
||||
// For string switches, sort the cases and emit the table data.
|
||||
llvm::Value *stringTableSlice = nullptr;
|
||||
const bool isStringSwitch = !stmt->condition->type->isintegral();
|
||||
if (isStringSwitch) {
|
||||
Logger::println("is string switch");
|
||||
assert(!irs->dcomputetarget);
|
||||
for (auto cs : *cases) {
|
||||
// skip over casts
|
||||
auto ce = cs->exp;
|
||||
while (ce->op == TOKcast)
|
||||
ce = static_cast<CastExp *>(ce)->e1;
|
||||
|
||||
// Sort the cases, taking care not to modify the original AST.
|
||||
cases = cases->copy();
|
||||
std::sort(cases->begin(), cases->end(), compareCaseStrings);
|
||||
|
||||
// Emit constants for the case values.
|
||||
llvm::SmallVector<llvm::Constant *, 16> stringConsts;
|
||||
stringConsts.reserve(caseCount);
|
||||
for (size_t i = 0; i < caseCount; ++i) {
|
||||
stringConsts.push_back(toConstElem((*cases)[i]->exp, irs));
|
||||
indices.push_back(DtoConstUint(i));
|
||||
}
|
||||
|
||||
// Create internal global with the data table.
|
||||
const auto elemTy = DtoType(stmt->condition->type);
|
||||
const auto arrTy = llvm::ArrayType::get(elemTy, stringConsts.size());
|
||||
const auto arrInit = LLConstantArray::get(arrTy, stringConsts);
|
||||
const auto arr = new llvm::GlobalVariable(
|
||||
irs->module, arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit,
|
||||
".string_switch_table_data");
|
||||
|
||||
// Create D slice to pass to runtime later.
|
||||
const auto arrPtr =
|
||||
llvm::ConstantExpr::getBitCast(arr, getPtrToType(elemTy));
|
||||
const auto arrLen = DtoConstSize_t(stringConsts.size());
|
||||
stringTableSlice = DtoConstSlice(arrLen, arrPtr);
|
||||
} else {
|
||||
for (auto cs : *cases) {
|
||||
// skip over casts
|
||||
auto ce = cs->exp;
|
||||
while (ce->op == TOKcast)
|
||||
ce = static_cast<CastExp *>(ce)->e1;
|
||||
|
||||
if (ce->op == TOKvar) {
|
||||
const auto vd = static_cast<VarExp *>(ce)->var->isVarDeclaration();
|
||||
if (vd && (!vd->_init || !vd->isConst())) {
|
||||
indices.push_back(DtoRVal(toElemDtor(cs->exp)));
|
||||
useSwitchInst = false;
|
||||
continue;
|
||||
}
|
||||
if (ce->op == TOKvar) {
|
||||
const auto vd = static_cast<VarExp *>(ce)->var->isVarDeclaration();
|
||||
if (vd && (!vd->_init || !vd->isConst())) {
|
||||
indices.push_back(DtoRVal(toElemDtor(cs->exp)));
|
||||
useSwitchInst = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
indices.push_back(toConstElem(cs->exp, irs));
|
||||
}
|
||||
|
||||
indices.push_back(toConstElem(cs->exp, irs));
|
||||
}
|
||||
assert(indices.size() == caseCount);
|
||||
|
||||
|
@ -987,12 +910,7 @@ public:
|
|||
irs->scope() = IRScope(oldbb);
|
||||
if (useSwitchInst) {
|
||||
// The case index value.
|
||||
LLValue *condVal;
|
||||
if (isStringSwitch) {
|
||||
condVal = call_string_switch_runtime(stringTableSlice, stmt->condition);
|
||||
} else {
|
||||
condVal = DtoRVal(toElemDtor(stmt->condition));
|
||||
}
|
||||
LLValue *condVal = DtoRVal(toElemDtor(stmt->condition));
|
||||
|
||||
// Create switch and add the cases.
|
||||
// For PGO instrumentation, we need to add counters /before/ the case
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue