Beispiel #1
0
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
{
#if 0
    printf("StaticIfCondition::include(sc = %p, s = %p) this=%p inc = %d\n", sc, s, this, inc);
    if (s)
    {
        printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
    }
#endif
    if (inc == 0)
    {
        if (exp->op == TOKerror || nest > 100)
        {
            error(loc, (nest > 1000) ? "unresolvable circular static if expression"
                                     : "error evaluating static if expression");
            if (!global.gag)
                inc = 2;                // so we don't see the error message again
            return 0;
        }

        if (!sc)
        {
            error(loc, "static if conditional cannot be at global scope");
            inc = 2;
            return 0;
        }

        ++nest;
        sc = sc->push(sc->scopesym);
        sc->sd = s;                     // s gets any addMember()
        sc->flags |= SCOPEstaticif;
        Expression *e = exp->semantic(sc);
        e = resolveProperties(sc, e);
        sc->pop();
        if (!e->type->checkBoolean())
        {
            if (e->type->toBasetype() != Type::terror)
                exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
            inc = 0;
            return 0;
        }
        e = e->ctfeInterpret();
        --nest;
        if (e->op == TOKerror)
        {   exp = e;
            inc = 0;
        }
        else if (e->isBool(TRUE))
            inc = 1;
        else if (e->isBool(FALSE))
            inc = 2;
        else
        {
            e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
            inc = 2;
        }
    }
    return (inc == 1);
}
Beispiel #2
0
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
{
#if 0
    printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
    if (s)
    {
        printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
    }
#endif
    if (inc == 0)
    {
        if (!sc)
        {
            error(loc, "static if conditional cannot be at global scope");
            inc = 2;
            return 0;
        }

        sc = sc->push(sc->scopesym);
        sc->sd = s;                     // s gets any addMember()
        sc->flags |= SCOPEstaticif;
        Expression *e = exp->semantic(sc);
        sc->pop();
        e = e->optimize(WANTvalue | WANTinterpret);
        if (e->isBool(TRUE))
            inc = 1;
        else if (e->isBool(FALSE))
            inc = 2;
        else
        {
            e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
            inc = 2;
        }
    }
    return (inc == 1);
}
Beispiel #3
0
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *sds)
{
#if 0
    printf("StaticIfCondition::include(sc = %p, sds = %p) this=%p inc = %d\n", sc, sds, this, inc);
    if (sds)
    {
        printf("\ts = '%s', kind = %s\n", sds->toChars(), sds->kind());
    }
#endif
    if (inc == 0)
    {
        if (exp->op == TOKerror || nest > 100)
        {
            error(loc, (nest > 1000) ? "unresolvable circular static if expression"
                                     : "error evaluating static if expression");
            goto Lerror;
        }

        if (!sc)
        {
            error(loc, "static if conditional cannot be at global scope");
            inc = 2;
            return 0;
        }

        ++nest;
        sc = sc->push(sc->scopesym);
        sc->sds = sds;                  // sds gets any addMember()
        //sc->speculative = true;       // TODO: static if (is(T U)) { /* U is available */ }
        sc->flags |= SCOPEcondition;

        sc = sc->startCTFE();
        Expression *e = exp->semantic(sc);
        e = resolveProperties(sc, e);
        sc = sc->endCTFE();

        sc->pop();
        --nest;

        // Prevent repeated condition evaluation.
        // See: fail_compilation/fail7815.d
        if (inc != 0)
            return (inc == 1);

        if (!e->type->isBoolean())
        {
            if (e->type->toBasetype() != Type::terror)
                exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
            goto Lerror;
        }
        e = e->ctfeInterpret();
        if (e->op == TOKerror)
        {
            goto Lerror;
        }
        else if (e->isBool(true))
            inc = 1;
        else if (e->isBool(false))
            inc = 2;
        else
        {
            e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
            goto Lerror;
        }
    }
    return (inc == 1);

Lerror:
    if (!global.gag)
        inc = 2;                // so we don't see the error message again
    return 0;
}
Beispiel #4
0
DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd, Expressions *arguments,
                         LLValue *sretPointer) {
  IF_LOG Logger::println("DtoInlineAsmExpr @ %s", loc.toChars());
  LOG_SCOPE;

  assert(fd->toParent()->isTemplateInstance() && "invalid inline __asm expr");
  assert(arguments->dim >= 2 && "invalid __asm call");

  // get code param
  Expression *e = (*arguments)[0];
  IF_LOG Logger::println("code exp: %s", e->toChars());
  StringExp *se = static_cast<StringExp *>(e);
  if (e->op != TOKstring || se->sz != 1) {
    e->error("`__asm` code argument is not a `char[]` string literal");
    fatal();
  }
  std::string code(se->toPtr(), se->numberOfCodeUnits());

  // get constraints param
  e = (*arguments)[1];
  IF_LOG Logger::println("constraint exp: %s", e->toChars());
  se = static_cast<StringExp *>(e);
  if (e->op != TOKstring || se->sz != 1) {
    e->error("`__asm` constraints argument is not a `char[]` string literal");
    fatal();
  }
  std::string constraints(se->toPtr(), se->numberOfCodeUnits());

  // build runtime arguments
  size_t n = arguments->dim;

  LLSmallVector<llvm::Value *, 8> args;
  args.reserve(n - 2);
  std::vector<LLType *> argtypes;
  argtypes.reserve(n - 2);

  for (size_t i = 2; i < n; i++) {
    args.push_back(DtoRVal((*arguments)[i]));
    argtypes.push_back(args.back()->getType());
  }

  // build asm function type
  Type *type = fd->type->nextOf();
  LLType *ret_type = DtoType(type->toBasetype());
  llvm::FunctionType *FT = llvm::FunctionType::get(ret_type, argtypes, false);

  // make sure the constraints are valid
  if (!llvm::InlineAsm::Verify(FT, constraints)) {
    e->error("`__asm` constraint argument is invalid");
    fatal();
  }

  // build asm call
  bool sideeffect = true;
  llvm::InlineAsm *ia = llvm::InlineAsm::get(FT, code, constraints, sideeffect);

  llvm::Value *rv = gIR->ir->CreateCall(ia, args, "");

  if (sretPointer) {
    DtoStore(rv, DtoBitCast(sretPointer, getPtrToType(ret_type)));
    return new DLValue(type, sretPointer);
  }

  // work around missing tuple support for users of the return value
  if (type->ty == Tstruct) {
    // make a copy
    llvm::Value *mem = DtoAlloca(type, ".__asm_tuple_ret");
    DtoStore(rv, DtoBitCast(mem, getPtrToType(ret_type)));
    return new DLValue(type, mem);
  }

  // return call as im value
  return new DImValue(type, rv);
}
Beispiel #5
0
DValue * DtoInlineAsmExpr(Loc loc, FuncDeclaration * fd, Expressions * arguments)
{
    Logger::println("DtoInlineAsmExpr @ %s", loc.toChars());
    LOG_SCOPE;

    TemplateInstance* ti = fd->toParent()->isTemplateInstance();
    assert(ti && "invalid inline __asm expr");

    assert(arguments->dim >= 2 && "invalid __asm call");

    // get code param
    Expression* e = static_cast<Expression*>(arguments->data[0]);
    Logger::println("code exp: %s", e->toChars());
    StringExp* se = static_cast<StringExp*>(e);
    if (e->op != TOKstring || se->sz != 1)
    {
        e->error("__asm code argument is not a char[] string literal");
        fatal();
    }
    std::string code(static_cast<char*>(se->string), se->len);

    // get constraints param
    e = static_cast<Expression*>(arguments->data[1]);
    Logger::println("constraint exp: %s", e->toChars());
    se = static_cast<StringExp*>(e);
    if (e->op != TOKstring || se->sz != 1)
    {
        e->error("__asm constraints argument is not a char[] string literal");
        fatal();
    }
    std::string constraints(static_cast<char*>(se->string), se->len);

    // build runtime arguments
    size_t n = arguments->dim;

    LLSmallVector<llvm::Value*, 8> args;
    args.reserve(n-2);
    std::vector<LLType*> argtypes;
    argtypes.reserve(n-2);

    for (size_t i = 2; i < n; i++)
    {
        e = static_cast<Expression*>(arguments->data[i]);
        args.push_back(e->toElem(gIR)->getRVal());
        argtypes.push_back(args.back()->getType());
    }

    // build asm function type
    Type* type = fd->type->nextOf()->toBasetype();
    LLType* ret_type = DtoType(type);
    llvm::FunctionType* FT = llvm::FunctionType::get(ret_type, argtypes, false);

    // build asm call
    bool sideeffect = true;
    llvm::InlineAsm* ia = llvm::InlineAsm::get(FT, code, constraints, sideeffect);

    llvm::Value* rv = gIR->ir->CreateCall(ia, args, "");

    // work around missing tuple support for users of the return value
    if (type->ty == Tstruct)
    {
        // make a copy
        llvm::Value* mem = DtoAlloca(type, ".__asm_tuple_ret");

        TypeStruct* ts = static_cast<TypeStruct*>(type);
        size_t n = ts->sym->fields.dim;
        for (size_t i = 0; i < n; i++)
        {
            llvm::Value* v = gIR->ir->CreateExtractValue(rv, i, "");
            llvm::Value* gep = DtoGEPi(mem, 0, i);
            DtoStore(v, gep);
        }

        return new DVarValue(fd->type->nextOf(), mem);
    }

    // return call as im value
    return new DImValue(fd->type->nextOf(), rv);
}