Ejemplo n.º 1
0
// XXX: to be refactored
// This function repeats the logic in cg to pre-color tmps that are
// going to be used in next native.
void LinearScan::computePreColoringHint() {
  m_preColoringHint.clear();
  IRInstruction* nextNative = getNextNative();
  if (nextNative == NULL) {
    return;
  }
  Opcode opc = nextNative->getOpcode();
  switch (opc) {
    case Box:
      if (nextNative->getSrc(0)->getType() == Type::Cell) {
        m_preColoringHint.add(nextNative->getSrc(0), 1, 0);
      }
      m_preColoringHint.add(nextNative->getSrc(0), 0, 1);
      break;
    case LdObjMethod:
      m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
      m_preColoringHint.add(nextNative->getSrc(0), 0, 2);
      break;
    case LdFunc:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 1);
      break;
    case NativeImpl:
      m_preColoringHint.add(nextNative->getSrc(1), 0, 0);
      break;
    case DecRefLocals:
    case DecRefLocalsThis:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
      break;
    case Print:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      break;
    case AddElem:
      if (nextNative->getSrc(1)->getType() == Type::Int &&
          nextNative->getSrc(2)->getType() == Type::Int) {
        m_preColoringHint.add(nextNative->getSrc(0), 0, 1);
        m_preColoringHint.add(nextNative->getSrc(1), 0, 2);
        m_preColoringHint.add(nextNative->getSrc(2), 0, 3);
      } else {
        m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
        m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
        m_preColoringHint.add(nextNative->getSrc(2), 0, 2);
        m_preColoringHint.add(nextNative->getSrc(2), 1, 3);
      }
      break;
    case AddNewElem:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
      m_preColoringHint.add(nextNative->getSrc(1), 1, 2);
      break;
    case Concat:
      {
        Type::Tag lType = nextNative->getSrc(0)->getType();
        Type::Tag rType = nextNative->getSrc(1)->getType();
        if ((Type::isString(lType) && Type::isString(rType)) ||
            (Type::isString(lType) && rType == Type::Int) ||
            (lType == Type::Int && Type::isString(rType))) {
          m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
          m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
        } else {
          m_preColoringHint.add(nextNative->getSrc(0), 0, 1);
          m_preColoringHint.add(nextNative->getSrc(1), 0, 3);
        }
      }
      break;
    case ArrayAdd:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
      break;
    case DefFunc:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      break;
    case CreateCont:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
      m_preColoringHint.add(nextNative->getSrc(2), 0, 2);
      m_preColoringHint.add(nextNative->getSrc(3), 0, 3);
      break;
    case FillContLocals:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
      m_preColoringHint.add(nextNative->getSrc(2), 0, 2);
      m_preColoringHint.add(nextNative->getSrc(3), 0, 3);
      break;
    case OpEq:
    case OpNeq:
    case OpSame:
    case OpNSame:
      {
        auto src1 = nextNative->getSrc(0);
        auto src2 = nextNative->getSrc(1);

        auto type1 = src1->getType();
        auto type2 = src2->getType();

        if ((type1 == Type::Arr && type2 == Type::Arr)
            || (Type::isString(type1) && Type::isString(type2))
            || (Type::isString(type1) && !src1->isConst())
            || (type1 == Type::Obj && type2 == Type::Obj)) {
          m_preColoringHint.add(src1, 0, 0);
          m_preColoringHint.add(src2, 0, 1);
        }
      }
      break;
    case Conv:
    {
      SSATmp* src = nextNative->getSrc(0);
      Type::Tag toType = nextNative->getType();
      Type::Tag fromType = src->getType();
      if (toType == Type::Bool) {
        switch (fromType) {
          case Type::Cell:
            m_preColoringHint.add(src, 0, 0);
            m_preColoringHint.add(src, 1, 1);
            break;
          case Type::Str:
          case Type::StaticStr:
          case Type::Arr:
          case Type::Obj:
            m_preColoringHint.add(src, 0, 0);
            break;
          default:
            break;
        }
      } else if (Type::isString(toType)) {
        if (fromType == Type::Int) {
          m_preColoringHint.add(src, 0, 0);
        }
      } else if (Type::isString(fromType) && toType == Type::Int) {
        m_preColoringHint.add(src, 0, 0);
      }
      break;
    }
    default:
      break;
  }
}
Ejemplo n.º 2
0
bool SSATmp::getValBool() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::Bool));
  return m_inst->extra<ConstData>()->as<bool>();
}
Ejemplo n.º 3
0
int64_t SSATmp::getValRawInt() const {
  assert(isConst());
  return m_inst->extra<ConstData>()->as<int64_t>();
}
Ejemplo n.º 4
0
int cs6300::MultExpression::value() const
{
  if (!isConst()) return 0;
  return m_lhs->value() * m_rhs->value();
}
Ejemplo n.º 5
0
int cs6300::AdditionExpression::value() const
{
  if (!isConst()) return 0;
  return m_lhs->value() + m_rhs->value();
}
Ejemplo n.º 6
0
Archivo: cppmangle.c Proyecto: yazd/dmd
void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{   char c;
    char p = 0;

    /* ABI spec says:
     * v        void
     * w        wchar_t
     * b        bool
     * c        char
     * a        signed char
     * h        unsigned char
     * s        short
     * t        unsigned short
     * i        int
     * j        unsigned int
     * l        long
     * m        unsigned long
     * x        long long, __int64
     * y        unsigned long long, __int64
     * n        __int128
     * o        unsigned __int128
     * f        float
     * d        double
     * e        long double, __float80
     * g        __float128
     * z        ellipsis
     * u <source-name>  # vendor extended type
     */

    switch (ty)
    {
        case Tvoid:     c = 'v';        break;
        case Tint8:     c = 'a';        break;
        case Tuns8:     c = 'h';        break;
        case Tint16:    c = 's';        break;
        case Tuns16:    c = 't';        break;
        case Tint32:    c = 'i';        break;
        case Tuns32:    c = 'j';        break;
        case Tfloat32:  c = 'f';        break;
        case Tint64:    c = 'x';        break;
        case Tuns64:    c = 'y';        break;
        case Tfloat64:  c = 'd';        break;
        case Tfloat80:  c = 'e';        break;
        case Tbool:     c = 'b';        break;
        case Tchar:     c = 'c';        break;
        case Twchar:    c = 't';        break;
        case Tdchar:    c = 'w';        break;

        case Timaginary32: p = 'G'; c = 'f';    break;
        case Timaginary64: p = 'G'; c = 'd';    break;
        case Timaginary80: p = 'G'; c = 'e';    break;
        case Tcomplex32:   p = 'C'; c = 'f';    break;
        case Tcomplex64:   p = 'C'; c = 'd';    break;
        case Tcomplex80:   p = 'C'; c = 'e';    break;

        default:        assert(0);
    }
    if (p || isConst())
    {
        if (cms->substitute(buf, this))
            return;
    }

    if (isConst())
        buf->writeByte('K');

    if (p)
        buf->writeByte(p);

    buf->writeByte(c);
}
Ejemplo n.º 7
0
std::shared_ptr<cs6300::BasicBlock> cs6300::AndExpression::emit() const
{
  if(isConst())
      return LiteralExpression::emit(value(), getLabel());
  return emitBinaryOp(ThreeAddressInstruction::And,getLabel(),m_lhs,m_rhs);
}
Ejemplo n.º 8
0
int BuiltinCallNode::foldConsts(VSLDef *cdef, VSLNode** node)
{
    // Apply standard optimization
    int changes = CallNode::foldConsts(cdef, node);

    // If optimization was a success, return
    if (*node != this || isConst())
	return changes;

    // If non-associative, return
    if (!VSLBuiltin::isAssoc(_index))
	return changes;

    // Otherwise: isolate constant args in constant subexpressions and
    // optimize them separately
    for (VSLNode *a = arg();
	 a->isListNode() && ((ListNode *)a)->tail()->isListNode();
	 a = ((ListNode *)a)->tail())
    {
	ListNode *list = (ListNode *)a;
	ListNode *tail = (ListNode *)list->tail();

	VSLNode *arg1 = list->head();
	VSLNode *arg2 = tail->head();

	if (arg1->isConst() && arg2->isConst())
	{
	    if (VSEFlags::show_optimize)
	    {
		std::cout << "\n" << cdef->longname() << ": foldConsts: replacing\n"
		    << *this << '\n';
		std::cout.flush();
	    }

	    // Found 2 args arg1, arg2 that are both constant: Replace
	    // f(..., arg1, arg2, ...) by f(..., f(arg1, arg2), ...)

	    // Create f(arg1, arg2)
	    ListNode *new_args = new FixListNode(arg1, arg2);
	    BuiltinCallNode *new_f = new BuiltinCallNode(_index, new_args);

	    // Move nextarg into f(arg, nextarg)
	    list->head() = new_f;
	    list->tail() = tail->tail();

	    tail->head() = 0; tail->tail() = 0; delete tail;

	    if (VSEFlags::show_optimize)
	    {
		std::cout << "by " << *this << '\n';
		std::cout.flush();
	    }

	    changes++;
	}
    }

    // Now try optimization once again
    changes += CallNode::foldConsts(cdef, node);

    return changes;
}
Ejemplo n.º 9
0
// XXX: to be refactored
// This function repeats the logic in cg to pre-color tmps that are
// going to be used in next native.
void LinearScan::computePreColoringHint() {
  m_preColoringHint.clear();
  IRInstruction* nextNative = getNextNative();
  if (nextNative == NULL) {
    return;
  }
  auto normalHint = [&](int count, int srcBase = 0, int argBase = 0) {
    for (int i = 0; i < count; ++i) {
      m_preColoringHint.add(nextNative->getSrc(i + srcBase), 0,
                            i + argBase);
    }
  };
  switch (nextNative->getOpcode()) {
    case Box:
      if (nextNative->getSrc(0)->getType() == Type::Cell) {
        m_preColoringHint.add(nextNative->getSrc(0), 1, 0);
      }
      m_preColoringHint.add(nextNative->getSrc(0), 0, 1);
      break;
    case LdObjMethod:
      m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
      m_preColoringHint.add(nextNative->getSrc(0), 0, 2);
      break;
    case LdFunc:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 1);
      break;
    case NativeImpl:
      m_preColoringHint.add(nextNative->getSrc(1), 0, 0);
      break;
    case Print:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      break;
    case AddElem:
      if (nextNative->getSrc(1)->getType() == Type::Int &&
          nextNative->getSrc(2)->getType() == Type::Int) {
        normalHint(3, 0, 1);
      } else {
        m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
        m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
        m_preColoringHint.add(nextNative->getSrc(2), 0, 2);
        m_preColoringHint.add(nextNative->getSrc(2), 1, 3);
      }
      break;
    case AddNewElem:
      m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
      m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
      m_preColoringHint.add(nextNative->getSrc(1), 1, 2);
      break;
    case Concat:
      {
        Type::Tag lType = nextNative->getSrc(0)->getType();
        Type::Tag rType = nextNative->getSrc(1)->getType();
        if ((Type::isString(lType) && Type::isString(rType)) ||
            (Type::isString(lType) && rType == Type::Int) ||
            (lType == Type::Int && Type::isString(rType))) {
          m_preColoringHint.add(nextNative->getSrc(0), 0, 0);
          m_preColoringHint.add(nextNative->getSrc(1), 0, 1);
        } else {
          m_preColoringHint.add(nextNative->getSrc(0), 0, 1);
          m_preColoringHint.add(nextNative->getSrc(1), 0, 3);
        }
      }
      break;
    case ArrayAdd:
      normalHint(2);
      break;
    case DefFunc:
      normalHint(1);
      break;
    case CreateCont:
      normalHint(4);
      break;
    case FillContLocals:
      normalHint(4);
      break;
    case OpEq:
    case OpNeq:
    case OpSame:
    case OpNSame:
      {
        auto src1 = nextNative->getSrc(0);
        auto src2 = nextNative->getSrc(1);

        auto type1 = src1->getType();
        auto type2 = src2->getType();

        if ((type1 == Type::Arr && type2 == Type::Arr)
            || (Type::isString(type1) && Type::isString(type2))
            || (Type::isString(type1) && !src1->isConst())
            || (type1 == Type::Obj && type2 == Type::Obj)) {
          m_preColoringHint.add(src1, 0, 0);
          m_preColoringHint.add(src2, 0, 1);
        }
      }
      break;
    case IterInit:
    {
      m_preColoringHint.add(nextNative->getSrc(0), 0, 1);
    }
    break;
    case Conv:
    {
      SSATmp* src = nextNative->getSrc(0);
      Type::Tag toType = nextNative->getTypeParam();
      Type::Tag fromType = src->getType();
      if (toType == Type::Bool) {
        switch (fromType) {
          case Type::Cell:
            m_preColoringHint.add(src, 0, 0);
            m_preColoringHint.add(src, 1, 1);
            break;
          case Type::Str:
          case Type::StaticStr:
          case Type::Arr:
          case Type::Obj:
            m_preColoringHint.add(src, 0, 0);
            break;
          default:
            break;
        }
      } else if (Type::isString(toType)) {
        if (fromType == Type::Int) {
          m_preColoringHint.add(src, 0, 0);
        }
      } else if (Type::isString(fromType) && toType == Type::Int) {
        m_preColoringHint.add(src, 0, 0);
      }
      break;
    }
    default:
      break;
  }
}
Ejemplo n.º 10
0
void VarDeclaration::codegen(Ir* p)
{
    Logger::print("VarDeclaration::codegen(): %s | %s\n", toChars(), type->toChars());
    LOG_SCOPE;

    if (type->ty == Terror)
    {   error("had semantic errors when compiling");
        return;
    }

    // just forward aliases
    if (aliassym)
    {
        Logger::println("alias sym");
        toAlias()->codegen(p);
        return;
    }

    // output the parent aggregate first
    if (AggregateDeclaration* ad = isMember())
        ad->codegen(p);

    // global variable
    if (isDataseg() || (storage_class & (STCconst | STCimmutable) && init))
    {
        Logger::println("data segment");

    #if 0 // TODO:
        assert(!(storage_class & STCmanifest) &&
            "manifest constant being codegen'd!");
    #endif

        // don't duplicate work
        if (this->ir.resolved) return;
        this->ir.resolved = true;
        this->ir.declared = true;

        this->ir.irGlobal = new IrGlobal(this);

        Logger::println("parent: %s (%s)", parent->toChars(), parent->kind());

        const bool isLLConst = isConst() && init;
        const llvm::GlobalValue::LinkageTypes llLinkage = DtoLinkage(this);

        assert(!ir.initialized);
        ir.initialized = gIR->dmodule;
        std::string llName(mangle());

        // Since the type of a global must exactly match the type of its
        // initializer, we cannot know the type until after we have emitted the
        // latter (e.g. in case of unions, …). However, it is legal for the
        // initializer to refer to the address of the variable. Thus, we first
        // create a global with the generic type (note the assignment to
        // this->ir.irGlobal->value!), and in case we also do an initializer
        // with a different type later, swap it out and replace any existing
        // uses with bitcasts to the previous type.
        llvm::GlobalVariable* gvar = getOrCreateGlobal(loc, *gIR->module,
            i1ToI8(DtoType(type)), isLLConst, llLinkage, 0, llName,
            isThreadlocal());
        this->ir.irGlobal->value = gvar;

        // Check if we are defining or just declaring the global in this module.
        if (!(storage_class & STCextern) && mustDefineSymbol(this))
        {
            // Build the initializer. Might use this->ir.irGlobal->value!
            LLConstant *initVal = DtoConstInitializer(loc, type, init);

            // In case of type mismatch, swap out the variable.
            if (initVal->getType() != gvar->getType()->getElementType())
            {
                llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc,
                    *gIR->module, initVal->getType(), isLLConst, llLinkage, 0,
                    "", // We take on the name of the old global below.
                    isThreadlocal());

                newGvar->takeName(gvar);

                llvm::Constant* newValue =
                    llvm::ConstantExpr::getBitCast(newGvar, gvar->getType());
                gvar->replaceAllUsesWith(newValue);

                gvar->eraseFromParent();
                gvar = newGvar;
                this->ir.irGlobal->value = newGvar;
            }

            // Now, set the initializer.
            assert(!ir.irGlobal->constInit);
            ir.irGlobal->constInit = initVal;
            gvar->setInitializer(initVal);

            // Also set up the edbug info.
            DtoDwarfGlobalVariable(gvar, this);
        }

        // Set the alignment (it is important not to use type->alignsize because
        // VarDeclarations can have an align() attribute independent of the type
        // as well).
        if (alignment != STRUCTALIGN_DEFAULT)
            gvar->setAlignment(alignment);

        // If this global is used from a naked function, we need to create an
        // artificial "use" for it, or it could be removed by the optimizer if
        // the only reference to it is in inline asm.
        if (nakedUse)
            gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));

        if (Logger::enabled())
            Logger::cout() << *gvar << '\n';
    }
}
Ejemplo n.º 11
0
String ConversionOperator::basicCode(FunctionCodeScope _ref) const
{
	return Martta::code(qualifiers() & FunctionMask) + callingCode(_ref) + (isConst() ? " const" : "");
}
Ejemplo n.º 12
0
void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
{
    if (sc->incontract && isParameter())
        error(loc, "cannot modify parameter '%s' in contract", toChars());

    if (sc->incontract && isResult())
        error(loc, "cannot modify result '%s' in contract", toChars());

    if (isCtorinit() && !t->isMutable())
    {   // It's only modifiable if inside the right constructor
        Dsymbol *s = sc->func;
        while (1)
        {
            FuncDeclaration *fd = NULL;
            if (s)
                fd = s->isFuncDeclaration();
            if (fd &&
                ((fd->isCtorDeclaration() && storage_class & STCfield) ||
                 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
                fd->toParent() == toParent()
               )
            {
                VarDeclaration *v = isVarDeclaration();
                assert(v);
                v->ctorinit = 1;
                //printf("setting ctorinit\n");
            }
            else
            {
                if (s)
                {   s = s->toParent2();
                    continue;
                }
                else
                {
                    const char *p = isStatic() ? "static " : "";
                    error(loc, "can only initialize %sconst %s inside %sconstructor",
                        p, toChars(), p);
                }
            }
            break;
        }
    }
    else
    {
        VarDeclaration *v = isVarDeclaration();
        if (v && v->canassign == 0)
        {
            const char *p = NULL;
            if (isConst())
                p = "const";
            else if (isImmutable())
                p = "immutable";
            else if (storage_class & STCmanifest)
                p = "enum";
            else if (!t->isAssignable())
                p = "struct with immutable members";
            if (p)
            {   error(loc, "cannot modify %s", p);
            }
        }
    }
}
Ejemplo n.º 13
0
void VarDeclaration::semantic(Scope *sc)
{
#if 0
    printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
    printf(" type = %s\n", type ? type->toChars() : "null");
    printf(" stc = x%x\n", sc->stc);
    printf(" storage_class = x%x\n", storage_class);
    printf("linkage = %d\n", sc->linkage);
    //if (strcmp(toChars(), "mul") == 0) halt();
#endif

    storage_class |= sc->stc;
    if (storage_class & STCextern && init)
        error("extern symbols cannot have initializers");

    /* If auto type inference, do the inference
     */
    int inferred = 0;
    if (!type)
    {   inuse++;
        type = init->inferType(sc);
        inuse--;
        inferred = 1;

        /* This is a kludge to support the existing syntax for RAII
         * declarations.
         */
        storage_class &= ~STCauto;
        originalType = type;
    }
    else
    {   if (!originalType)
            originalType = type;
        type = type->semantic(loc, sc);
    }
    //printf(" semantic type = %s\n", type ? type->toChars() : "null");

    type->checkDeprecated(loc, sc);
    linkage = sc->linkage;
    this->parent = sc->parent;
    //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
    protection = sc->protection;
    //printf("sc->stc = %x\n", sc->stc);
    //printf("storage_class = x%x\n", storage_class);

#if DMDV2
    if (storage_class & STCgshared && global.params.safe && !sc->module->safe)
    {
        error("__gshared not allowed in safe mode; use shared");
    }
#endif

    Dsymbol *parent = toParent();
    FuncDeclaration *fd = parent->isFuncDeclaration();

    Type *tb = type->toBasetype();
    if (tb->ty == Tvoid && !(storage_class & STClazy))
    {   error("voids have no value");
        type = Type::terror;
        tb = type;
    }
    if (tb->ty == Tfunction)
    {   error("cannot be declared to be a function");
        type = Type::terror;
        tb = type;
    }
    if (tb->ty == Tstruct)
    {   TypeStruct *ts = (TypeStruct *)tb;

        if (!ts->sym->members)
        {
            error("no definition of struct %s", ts->toChars());
        }
    }

    if (tb->ty == Ttuple)
    {   /* Instead, declare variables for each of the tuple elements
         * and add those.
         */
        TypeTuple *tt = (TypeTuple *)tb;
        size_t nelems = Parameter::dim(tt->arguments);
        Objects *exps = new Objects();
        exps->setDim(nelems);
        Expression *ie = init ? init->toExpression() : NULL;

        for (size_t i = 0; i < nelems; i++)
        {   Parameter *arg = Parameter::getNth(tt->arguments, i);

            OutBuffer buf;
            buf.printf("_%s_field_%zu", ident->toChars(), i);
            buf.writeByte(0);
            const char *name = (const char *)buf.extractData();
            Identifier *id = Lexer::idPool(name);

            Expression *einit = ie;
            if (ie && ie->op == TOKtuple)
            {   einit = (Expression *)((TupleExp *)ie)->exps->data[i];
            }
            Initializer *ti = init;
            if (einit)
            {   ti = new ExpInitializer(einit->loc, einit);
            }

            VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
            //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
            v->semantic(sc);

            if (sc->scopesym)
            {   //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
                if (sc->scopesym->members)
                    sc->scopesym->members->push(v);
            }

            Expression *e = new DsymbolExp(loc, v);
            exps->data[i] = e;
        }
        TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
        v2->isexp = 1;
        aliassym = v2;
        return;
    }

    if (storage_class & STCconst && !init && !fd)
        // Initialize by constructor only
        storage_class = (storage_class & ~STCconst) | STCctorinit;

    if (isConst())
    {
    }
    else if (isStatic())
    {
    }
    else if (isSynchronized())
    {
        error("variable %s cannot be synchronized", toChars());
    }
    else if (isOverride())
    {
        error("override cannot be applied to variable");
    }
    else if (isAbstract())
    {
        error("abstract cannot be applied to variable");
    }
    else if (storage_class & STCtemplateparameter)
    {
    }
    else if (storage_class & STCctfe)
    {
    }
    else
    {
        AggregateDeclaration *aad = sc->anonAgg;
        if (!aad)
            aad = parent->isAggregateDeclaration();
        if (aad)
        {
#if DMDV2
            assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared)));

            if (storage_class & (STCconst | STCimmutable) && init)
            {
                if (!type->toBasetype()->isTypeBasic())
                    storage_class |= STCstatic;
            }
            else
#endif
                aad->addField(sc, this);
        }

        InterfaceDeclaration *id = parent->isInterfaceDeclaration();
        if (id)
        {
            error("field not allowed in interface");
        }

        /* Templates cannot add fields to aggregates
         */
        TemplateInstance *ti = parent->isTemplateInstance();
        if (ti)
        {
            // Take care of nested templates
            while (1)
            {
                TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
                if (!ti2)
                    break;
                ti = ti2;
            }

            // If it's a member template
            AggregateDeclaration *ad = ti->tempdecl->isMember();
            if (ad && storage_class != STCundefined)
            {
                error("cannot use template to add field to aggregate '%s'", ad->toChars());
            }
        }
    }

#if DMDV2
    if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref &&
        ident != Id::This)
    {
        error("only parameters or foreach declarations can be ref");
    }
#endif

    if (type->isauto() && !noauto)
    {
        if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd)
        {
            error("globals, statics, fields, ref and out parameters cannot be auto");
        }

        if (!(storage_class & (STCauto | STCscope)))
        {
            if (!(storage_class & STCparameter) && ident != Id::withSym)
                error("reference to scope class must be scope");
        }
    }

    enum TOK op = TOKconstruct;
    if (!init && !sc->inunion && !isStatic() && !isConst() && fd &&
        !(storage_class & (STCfield | STCin | STCforeach)) &&
        type->size() != 0)
    {
        // Provide a default initializer
        //printf("Providing default initializer for '%s'\n", toChars());
        if (type->ty == Tstruct &&
            ((TypeStruct *)type)->sym->zeroInit == 1)
        {   /* If a struct is all zeros, as a special case
             * set it's initializer to the integer 0.
             * In AssignExp::toElem(), we check for this and issue
             * a memset() to initialize the struct.
             * Must do same check in interpreter.
             */
            Expression *e = new IntegerExp(loc, 0, Type::tint32);
            Expression *e1;
            e1 = new VarExp(loc, this);
            e = new AssignExp(loc, e1, e);
            e->op = TOKconstruct;
            e->type = e1->type;         // don't type check this, it would fail
            init = new ExpInitializer(loc, e);
            return;
        }
        else if (type->ty == Ttypedef)
        {   TypeTypedef *td = (TypeTypedef *)type;
            if (td->sym->init)
            {   init = td->sym->init;
                ExpInitializer *ie = init->isExpInitializer();
                if (ie)
                    // Make copy so we can modify it
                    init = new ExpInitializer(ie->loc, ie->exp);
            }
            else
                init = getExpInitializer();
        }
        else
        {
            init = getExpInitializer();
        }
        // Default initializer is always a blit
        op = TOKblit;
    }

    if (init)
    {
        sc = sc->push();
        sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref);

        ArrayInitializer *ai = init->isArrayInitializer();
        if (ai && tb->ty == Taarray)
        {
            init = ai->toAssocArrayInitializer();
        }

        StructInitializer *si = init->isStructInitializer();
        ExpInitializer *ei = init->isExpInitializer();

        // See if initializer is a NewExp that can be allocated on the stack
        if (ei && isScope() && ei->exp->op == TOKnew)
        {   NewExp *ne = (NewExp *)ei->exp;
            if (!(ne->newargs && ne->newargs->dim))
            {   ne->onstack = 1;
                onstack = 1;
                if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
                    onstack = 2;
            }
        }

        // If inside function, there is no semantic3() call
        if (sc->func)
        {
            // If local variable, use AssignExp to handle all the various
            // possibilities.
            if (fd && !isStatic() && !isConst() && !init->isVoidInitializer())
            {
                //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
                if (!ei)
                {
                    Expression *e = init->toExpression();
                    if (!e)
                    {
                        init = init->semantic(sc, type);
                        e = init->toExpression();
                        if (!e)
                        {   error("is not a static and cannot have static initializer");
                            return;
                        }
                    }
                    ei = new ExpInitializer(init->loc, e);
                    init = ei;
                }

                Expression *e1 = new VarExp(loc, this);

                Type *t = type->toBasetype();
                if (t->ty == Tsarray && !(storage_class & (STCref | STCout)))
                {
                    ei->exp = ei->exp->semantic(sc);
                    if (!ei->exp->implicitConvTo(type))
                    {
                        int dim = ((TypeSArray *)t)->dim->toInteger();
                        // If multidimensional static array, treat as one large array
                        while (1)
                        {
                            t = t->nextOf()->toBasetype();
                            if (t->ty != Tsarray)
                                break;
                            dim *= ((TypeSArray *)t)->dim->toInteger();
                            e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
                        }
                    }
                    e1 = new SliceExp(loc, e1, NULL, NULL);
                }
                else if (t->ty == Tstruct)
                {
                    ei->exp = ei->exp->semantic(sc);
                    ei->exp = resolveProperties(sc, ei->exp);
                    StructDeclaration *sd = ((TypeStruct *)t)->sym;
#if DMDV2
                    /* Look to see if initializer is a call to the constructor
                     */
                    if (sd->ctor &&             // there are constructors
                        ei->exp->type->ty == Tstruct && // rvalue is the same struct
                        ((TypeStruct *)ei->exp->type)->sym == sd &&
                        ei->exp->op == TOKstar)
                    {
                        /* Look for form of constructor call which is:
                         *    *__ctmp.ctor(arguments...)
                         */
                        PtrExp *pe = (PtrExp *)ei->exp;
                        if (pe->e1->op == TOKcall)
                        {   CallExp *ce = (CallExp *)pe->e1;
                            if (ce->e1->op == TOKdotvar)
                            {   DotVarExp *dve = (DotVarExp *)ce->e1;
                                if (dve->var->isCtorDeclaration())
                                {   /* It's a constructor call, currently constructing
                                     * a temporary __ctmp.
                                     */
                                    /* Before calling the constructor, initialize
                                     * variable with a bit copy of the default
                                     * initializer
                                     */
                                    Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc));
                                    e->op = TOKblit;
                                    e->type = t;
                                    ei->exp = new CommaExp(loc, e, ei->exp);

                                    /* Replace __ctmp being constructed with e1
                                     */
                                    dve->e1 = e1;
                                    return;
                                }
                            }
                        }
                    }
#endif
                    if (!ei->exp->implicitConvTo(type))
                    {
                        /* Look for opCall
                         * See bugzilla 2702 for more discussion
                         */
                        Type *ti = ei->exp->type->toBasetype();
                        // Don't cast away invariant or mutability in initializer
                        if (search_function(sd, Id::call) &&
                            /* Initializing with the same type is done differently
                             */
                            !(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc)))
                        {   // Rewrite as e1.call(arguments)
                            Expression * eCall = new DotIdExp(loc, e1, Id::call);
                            ei->exp = new CallExp(loc, eCall, ei->exp);
                        }
                    }
                }
                ei->exp = new AssignExp(loc, e1, ei->exp);
                ei->exp->op = TOKconstruct;
                canassign++;
                ei->exp = ei->exp->semantic(sc);
                canassign--;
                ei->exp->optimize(WANTvalue);
            }
            else
            {
                init = init->semantic(sc, type);
                if (fd && isConst() && !isStatic())
                {   // Make it static
                    storage_class |= STCstatic;
                }
            }
        }
        else if (isConst() || isFinal() ||
                 parent->isAggregateDeclaration())
        {
            /* Because we may need the results of a const declaration in a
             * subsequent type, such as an array dimension, before semantic2()
             * gets ordinarily run, try to run semantic2() now.
             * Ignore failure.
             */

            if (!global.errors && !inferred)
            {
                unsigned errors = global.errors;
                global.gag++;
                //printf("+gag\n");
                Expression *e;
                Initializer *i2 = init;
                inuse++;
                if (ei)
                {
                    e = ei->exp->syntaxCopy();
                    e = e->semantic(sc);
                    e = e->implicitCastTo(sc, type);
                }
                else if (si || ai)
                {   i2 = init->syntaxCopy();
                    i2 = i2->semantic(sc, type);
                }
                inuse--;
                global.gag--;
                //printf("-gag\n");
                if (errors != global.errors)    // if errors happened
                {
                    if (global.gag == 0)
                        global.errors = errors; // act as if nothing happened
#if DMDV2
                    /* Save scope for later use, to try again
                     */
                    scope = new Scope(*sc);
                    scope->setNoFree();
#endif
                }
                else if (ei)
                {
                    e = e->optimize(WANTvalue | WANTinterpret);
                    if (e->op == TOKint64 || e->op == TOKstring || e->op == TOKfloat64)
                    {
                        ei->exp = e;            // no errors, keep result
                    }
#if DMDV2
                    else
                    {
                        /* Save scope for later use, to try again
                         */
                        scope = new Scope(*sc);
                        scope->setNoFree();
                    }
#endif
                }
                else
                    init = i2;          // no errors, keep result
            }
        }
        sc = sc->pop();
    }
}
Ejemplo n.º 14
0
int VarDeclaration::isImportedSymbol()
{
    if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule()))
        return TRUE;
    return FALSE;
}
Ejemplo n.º 15
0
uintptr_t SSATmp::getValCctx() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::Cctx));
  return m_inst->extra<ConstData>()->as<uintptr_t>();
}
Ejemplo n.º 16
0
bool ModelTypeRef::match(ModelTypeRef const &typeRef) const
    {
    return(getDeclType() == typeRef.getDeclType() &&
            isConst() == typeRef.isConst() && isRefer() == typeRef.isRefer());
    }
Ejemplo n.º 17
0
const StringData* SSATmp::getValStr() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::StaticStr));
  return m_inst->extra<ConstData>()->as<const StringData*>();
}
Ejemplo n.º 18
0
const ArrayData* SSATmp::getValArr() const {
  assert(isConst());
  // TODO: Task #2124292, Reintroduce StaticArr
  assert(m_inst->typeParam() <= Type::Arr);
  return m_inst->extra<ConstData>()->as<const ArrayData*>();
}
Ejemplo n.º 19
0
TEST(Type, Const) {
  auto five = Type::cns(5);
  EXPECT_LT(five, Type::Int);
  EXPECT_NE(five, Type::Int);
  EXPECT_TRUE(five.isConst());
  EXPECT_EQ(5, five.intVal());
  EXPECT_TRUE(five.isConst(Type::Int));
  EXPECT_TRUE(five.isConst(5));
  EXPECT_FALSE(five.isConst(5.0));
  EXPECT_TRUE(Type::Gen.maybe(five));
  EXPECT_EQ(Type::Int, five | Type::Int);
  EXPECT_EQ(Type::Int, five | Type::cns(10));
  EXPECT_EQ(five, five | Type::cns(5));
  EXPECT_EQ(five, Type::cns(5) & five);
  EXPECT_EQ(five, five & Type::Int);
  EXPECT_EQ(five, Type::Gen & five);
  EXPECT_EQ("Int<5>", five.toString());
  EXPECT_EQ(five, five - Type::Arr);
  EXPECT_EQ(five, five - Type::cns(1));
  EXPECT_EQ(Type::Bottom, five - Type::Int);
  EXPECT_EQ(Type::Bottom, five - five);
  EXPECT_EQ(Type::Int, five.dropConstVal());
  EXPECT_TRUE(five.not(Type::cns(2)));

  auto True = Type::cns(true);
  EXPECT_EQ("Bool<true>", True.toString());
  EXPECT_LT(True, Type::Bool);
  EXPECT_NE(True, Type::Bool);
  EXPECT_TRUE(True.isConst());
  EXPECT_EQ(true, True.boolVal());
  EXPECT_TRUE(Type::Uncounted.maybe(True));
  EXPECT_FALSE(five <= True);
  EXPECT_FALSE(five > True);

  EXPECT_TRUE(five.not(True));
  EXPECT_EQ(Type::Int | Type::Bool, five | True);
  EXPECT_EQ(Type::Bottom, five & True);

  EXPECT_TRUE(Type::Uninit.isConst());
  EXPECT_TRUE(Type::InitNull.isConst());
  EXPECT_FALSE(Type::Null.isConst());
  EXPECT_FALSE((Type::Uninit | Type::Bool).isConst());
  EXPECT_FALSE(Type::Int.isConst());

  auto array = make_packed_array(1, 2, 3, 4);
  auto arrData = ArrayData::GetScalarArray(array.get());
  auto constArray = Type::cns(arrData);
  auto packedArray = Type::Arr.specialize(ArrayData::kPackedKind);
  auto mixedArray = Type::Arr.specialize(ArrayData::kMixedKind);

  EXPECT_TRUE(constArray <= packedArray);
  EXPECT_TRUE(constArray < packedArray);
  EXPECT_FALSE(packedArray <= constArray);
  EXPECT_TRUE(constArray <= constArray);
  EXPECT_FALSE(packedArray <= mixedArray);
  EXPECT_FALSE(mixedArray <= packedArray);
  EXPECT_FALSE(constArray <= mixedArray);
  EXPECT_EQ(constArray, constArray & packedArray);

  ArrayTypeTable::Builder ratBuilder;
  auto rat1 = ratBuilder.packedn(RepoAuthType::Array::Empty::No,
                                 RepoAuthType(RepoAuthType::Tag::Str));
  auto ratArray1 = Type::Arr.specialize(rat1);
  auto rat2 = ratBuilder.packedn(RepoAuthType::Array::Empty::No,
                                 RepoAuthType(RepoAuthType::Tag::Int));
  auto ratArray2 = Type::Arr.specialize(rat2);
  EXPECT_EQ(Type::Arr, ratArray1 & ratArray2);
  EXPECT_TRUE(ratArray1 < Type::Arr);
  EXPECT_TRUE(ratArray1 <= ratArray1);
  EXPECT_TRUE(ratArray1 < (Type::Arr|Type::Obj));
  EXPECT_FALSE(ratArray1 < ratArray2);
  EXPECT_NE(ratArray1, ratArray2);

  auto packedRat = packedArray & ratArray1;
  EXPECT_EQ("Arr<PackedKind:N([Str])>", packedRat.toString());
  EXPECT_TRUE(packedRat <= packedArray);
  EXPECT_TRUE(packedRat < packedArray);
  EXPECT_TRUE(packedRat <= ratArray1);
  EXPECT_TRUE(packedRat < ratArray1);
  EXPECT_EQ(packedRat, packedRat & packedArray);
  EXPECT_EQ(packedRat, packedRat & ratArray1);
}
Ejemplo n.º 20
0
const Func* SSATmp::getValFunc() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::Func));
  return m_inst->extra<ConstData>()->as<const Func*>();
}
Ejemplo n.º 21
0
int cs6300::AndExpression::value() const
{
  if (!isConst()) return 0;
  return m_lhs->value() && m_rhs->value();
}
Ejemplo n.º 22
0
const Class* SSATmp::getValClass() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::Cls));
  return m_inst->extra<ConstData>()->as<const Class*>();
}
Ejemplo n.º 23
0
bool
Argument::
isConstRef() const
{
    return isConst() && refType_ == RefType::LValue;
}
Ejemplo n.º 24
0
const NamedEntity* SSATmp::getValNamedEntity() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::NamedEntity));
  return m_inst->extra<ConstData>()->as<const NamedEntity*>();
}
Ejemplo n.º 25
0
bool Type::subtypeOf(Type t2) const {
  // First, check for any members in m_bits that aren't in t2.m_bits.
  if ((m_bits & t2.m_bits) != m_bits) return false;

  // If t2 is a constant, we must be the same constant or Bottom.
  if (t2.m_hasConstVal) {
    assert(!t2.isUnion());
    return m_bits == kBottom || (m_hasConstVal && m_extra == t2.m_extra);
  }

  // If t2 is specialized, we must either not be eligible for the same kind of
  // specialization (Int <= {Int|Arr<Packed>}) or have a specialization that is
  // a subtype of t2's specialization.
  if (t2.isSpecialized()) {
    if (t2.canSpecializeClass()) {
      if (!isSpecialized()) return false;

      //  Obj=A <:  Obj=A
      // Obj<=A <: Obj<=A
      if (m_class.isExact() == t2.m_class.isExact() &&
          getClass() == t2.getClass()) {
        return true;
      }

      //      A <: B
      // ----------------
      //  Obj=A <: Obj<=B
      // Obj<=A <: Obj<=B
      if (!t2.m_class.isExact()) return getClass()->classof(t2.getClass());
      return false;
    }

    assert(t2.canSpecializeArray());
    if (!canSpecializeArray()) return true;
    if (!isSpecialized()) return false;

    // Both types are specialized Arr types. "Specialized" in this context
    // means it has at least one of a RepoAuthType::Array* or (const ArrayData*
    // or ArrayData::ArrayKind). We may return false erroneously in cases where
    // a 100% accurate comparison of the specializations would be prohibitively
    // expensive.
    if (m_arrayInfo == t2.m_arrayInfo) return true;
    auto rat1 = getArrayType();
    auto rat2 = t2.getArrayType();

    if (rat1 != rat2 && !(rat1 && !rat2)) {
      // Different rats are only ok if rat1 is present and rat2 isn't. It's
      // possible for one rat to be a subtype of another rat or array kind, but
      // checking that can be very expensive.
      return false;
    }

    auto kind1 = getOptArrayKind();
    auto kind2 = t2.getOptArrayKind();
    assert(kind1 || kind2);
    if (kind1 && !kind2) return true;
    if (kind2 && !kind1) return false;
    if (*kind1 != *kind2) return false;

    // Same kinds but we still have to check for const arrays. a <= b iff they
    // have the same const array or a has a const array and b doesn't. If they
    // have the same non-nullptr const array the m_arrayInfo check up above
    // should've triggered.
    auto const1 = isConst() ? arrVal() : nullptr;
    auto const2 = t2.isConst() ? t2.arrVal() : nullptr;
    assert((!const1 && !const2) || const1 != const2);
    return const1 == const2 || (const1 && !const2);
  }

  return true;
}
Ejemplo n.º 26
0
uintptr_t SSATmp::getValBits() const {
  assert(isConst());
  return m_inst->extra<ConstData>()->as<uintptr_t>();
}
Ejemplo n.º 27
0
int64_t SSATmp::getValInt() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::Int));
  return m_inst->extra<ConstData>()->as<int64_t>();
}
Ejemplo n.º 28
0
TCA SSATmp::getValTCA() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::TCA));
  return m_inst->extra<ConstData>()->as<TCA>();
}
Ejemplo n.º 29
0
double SSATmp::getValDbl() const {
  assert(isConst());
  assert(m_inst->typeParam().equals(Type::Dbl));
  return m_inst->extra<ConstData>()->as<double>();
}
Ejemplo n.º 30
0
int cs6300::NeqExpression::value() const
{
  if (!isConst()) return 0;
  return m_lhs->value() != m_rhs->value();
}