Esempio n. 1
0
 virtual bool validate(const Type &ref, const Type &row) {
   return row.size() == ref.size();
 }
Esempio n. 2
0
    void visit(TypeInfoStructDeclaration *d)
    {
        //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());
        if (global.params.is64bit)
            verifyStructSize(Type::typeinfostruct, 17 * Target::ptrsize);
        else
            verifyStructSize(Type::typeinfostruct, 15 * Target::ptrsize);

        dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0); // vtbl for TypeInfo_Struct
        dtsize_t(pdt, 0);                        // monitor

        assert(d->tinfo->ty == Tstruct);

        TypeStruct *tc = (TypeStruct *)d->tinfo;
        StructDeclaration *sd = tc->sym;

        if (!sd->members)
            return;

        /* Put out:
         *  char[] name;
         *  void[] init;
         *  hash_t function(in void*) xtoHash;
         *  bool function(in void*, in void*) xopEquals;
         *  int function(in void*, in void*) xopCmp;
         *  string function(const(void)*) xtoString;
         *  StructFlags m_flags;
         *  //xgetMembers;
         *  xdtor;
         *  xpostblit;
         *  uint m_align;
         *  version (X86_64)
         *      TypeInfo m_arg1;
         *      TypeInfo m_arg2;
         *  xgetRTInfo
         */

        const char *name = sd->toPrettyChars();
        size_t namelen = strlen(name);
        dtsize_t(pdt, namelen);
        dtabytes(pdt, 0, namelen + 1, name);

        // void[] init;
        dtsize_t(pdt, sd->structsize);       // init.length
        if (sd->zeroInit)
            dtsize_t(pdt, 0);                // NULL for 0 initialization
        else
            dtxoff(pdt, sd->toInitializer(), 0);    // init.ptr

        if (FuncDeclaration *fd = search_toHash(sd))
        {
            dtxoff(pdt, fd->toSymbol(), 0);
            TypeFunction *tf = (TypeFunction *)fd->type;
            assert(tf->ty == Tfunction);
            /* I'm a little unsure this is the right way to do it. Perhaps a better
             * way would to automatically add these attributes to any struct member
             * function with the name "toHash".
             * So I'm leaving this here as an experiment for the moment.
             */
            if (!tf->isnothrow || tf->trust == TRUSTsystem /*|| tf->purity == PUREimpure*/)
                warning(fd->loc, "toHash() must be declared as extern (D) size_t toHash() const nothrow @safe, not %s", tf->toChars());
        }
        else
            dtsize_t(pdt, 0);

        if (sd->xeq)
            dtxoff(pdt, sd->xeq->toSymbol(), 0);
        else
            dtsize_t(pdt, 0);

        if (sd->xcmp)
            dtxoff(pdt, sd->xcmp->toSymbol(), 0);
        else
            dtsize_t(pdt, 0);

        if (FuncDeclaration *fd = search_toString(sd))
        {
            dtxoff(pdt, fd->toSymbol(), 0);
        }
        else
            dtsize_t(pdt, 0);

        // StructFlags m_flags;
        StructFlags::Type m_flags = 0;
        if (tc->hasPointers()) m_flags |= StructFlags::hasPointers;
        dtsize_t(pdt, m_flags);

    #if 0
        // xgetMembers
        FuncDeclaration *sgetmembers = sd->findGetMembers();
        if (sgetmembers)
            dtxoff(pdt, sgetmembers->toSymbol(), 0);
        else
            dtsize_t(pdt, 0);                        // xgetMembers
    #endif

        // xdtor
        FuncDeclaration *sdtor = sd->dtor;
        if (sdtor)
            dtxoff(pdt, sdtor->toSymbol(), 0);
        else
            dtsize_t(pdt, 0);                        // xdtor

        // xpostblit
        FuncDeclaration *spostblit = sd->postblit;
        if (spostblit && !(spostblit->storage_class & STCdisable))
            dtxoff(pdt, spostblit->toSymbol(), 0);
        else
            dtsize_t(pdt, 0);                        // xpostblit

        // uint m_align;
        dtsize_t(pdt, tc->alignsize());

        if (global.params.is64bit)
        {
            Type *t = sd->arg1type;
            for (int i = 0; i < 2; i++)
            {
                // m_argi
                if (t)
                {
                    t->genTypeInfo(NULL);
                    dtxoff(pdt, t->vtinfo->toSymbol(), 0);
                }
                else
                    dtsize_t(pdt, 0);

                t = sd->arg2type;
            }
        }

        // xgetRTInfo
        if (sd->getRTInfo)
            sd->getRTInfo->toDt(pdt);
        else if (m_flags & StructFlags::hasPointers)
            dtsize_t(pdt, 1);
        else
            dtsize_t(pdt, 0);
    }
Esempio n. 3
0
    void source_name(Dsymbol *s)
    {
        char *name = s->ident->toChars();
        TemplateInstance *ti = s->isTemplateInstance();
        if (ti)
        {
            if (!substitute(ti->tempdecl))
            {
                store(ti->tempdecl);
                name = ti->name->toChars();
                buf.printf("%d%s", strlen(name), name);
            }
            buf.writeByte('I');
            bool is_var_arg = false;
            for (size_t i = 0; i < ti->tiargs->dim; i++)
            {
                RootObject *o = (RootObject *)(*ti->tiargs)[i];

                TemplateParameter *tp = NULL;
                TemplateValueParameter *tv = NULL;
                TemplateTupleParameter *tt = NULL;
                if (!is_var_arg)
                {
                    TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration();
                    tp = (*td->parameters)[i];
                    tv = tp->isTemplateValueParameter();
                    tt = tp->isTemplateTupleParameter();
                }
                /*
                 *           <template-arg> ::= <type>            # type or template
                 *                          ::= <expr-primary>   # simple expressions
                 */

                if (tt)
                {
                    buf.writeByte('I');
                    is_var_arg = true;
                    tp = NULL;
                }

                if (tv)
                {
                    // <expr-primary> ::= L <type> <value number> E                   # integer literal
                    if (tv->valType->isintegral())
                    {
                        Expression* e = isExpression(o);
                        assert(e);
                        buf.writeByte('L');
                        tv->valType->accept(this);
                        if (tv->valType->isunsigned())
                        {
                            buf.printf("%llu", e->toUInteger());
                        }
                        else
                        {
                            dinteger_t val = e->toInteger();
                            if (val < 0)
                            {
                                val = -val;
                                buf.writeByte('n');
                            }
                            buf.printf("%lld", val);
                        }
                        buf.writeByte('E');
                    }
                    else
                    {
                        s->error("ICE: C++ %s template value parameter is not supported", tv->valType->toChars());
                        assert(0);
                    }
                }
                else if (!tp || tp->isTemplateTypeParameter())
                {
                    Type *t = isType(o);
                    assert(t);
                    t->accept(this);
                }
                else if (tp->isTemplateAliasParameter())
                {
                    Dsymbol* d = isDsymbol(o);
                    Expression* e = isExpression(o);
                    if (!d && !e)
                    {
                        s->error("ICE: %s is unsupported parameter for C++ template: (%s)", o->toChars());
                        assert(0);
                    }
                    if (d && d->isFuncDeclaration())
                    {
                        bool is_nested = d->toParent() && !d->toParent()->isModule() && ((TypeFunction *)d->isFuncDeclaration()->type)->linkage == LINKcpp;
                        if (is_nested) buf.writeByte('X');
                        buf.writeByte('L');
                        mangle_function(d->isFuncDeclaration());
                        buf.writeByte('E');
                        if (is_nested) buf.writeByte('E');
                    }
                    else if (e && e->op == TOKvar && ((VarExp*)e)->var->isVarDeclaration())
                    {
                        VarDeclaration *vd = ((VarExp*)e)->var->isVarDeclaration();
                        buf.writeByte('L');
                        mangle_variable(vd, true);
                        buf.writeByte('E');
                    }
                    else if (d && d->isTemplateDeclaration() && d->isTemplateDeclaration()->onemember)
                    {
                        if (!substitute(d))
                        {
                            cpp_mangle_name(d);
                            store(d);
                        }
                    }
                    else
                    {
                        s->error("ICE: %s is unsupported parameter for C++ template", o->toChars());
                        assert(0);
                    }

                }
                else
                {
                    s->error("ICE: C++ templates support only integral value , type parameters, alias templates and alias function parameters");
                    assert(0);
                }
            }
            if (is_var_arg)
            {
                buf.writeByte('E');
            }
            buf.writeByte('E');
            return;
        }
        else
        {
            buf.printf("%d%s", strlen(name), name);
        }
    }
Esempio n. 4
0
/// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination
/// register based on the LiveOutInfo of its operands.
void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) {
  Type *Ty = PN->getType();
  if (!Ty->isIntegerTy() || Ty->isVectorTy())
    return;

  const TargetLowering *TLI = TM.getSubtargetImpl()->getTargetLowering();

  SmallVector<EVT, 1> ValueVTs;
  ComputeValueVTs(*TLI, Ty, ValueVTs);
  assert(ValueVTs.size() == 1 &&
         "PHIs with non-vector integer types should have a single VT.");
  EVT IntVT = ValueVTs[0];

  if (TLI->getNumRegisters(PN->getContext(), IntVT) != 1)
    return;
  IntVT = TLI->getTypeToTransformTo(PN->getContext(), IntVT);
  unsigned BitWidth = IntVT.getSizeInBits();

  unsigned DestReg = ValueMap[PN];
  if (!TargetRegisterInfo::isVirtualRegister(DestReg))
    return;
  LiveOutRegInfo.grow(DestReg);
  LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg];

  Value *V = PN->getIncomingValue(0);
  if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
    DestLOI.NumSignBits = 1;
    APInt Zero(BitWidth, 0);
    DestLOI.KnownZero = Zero;
    DestLOI.KnownOne = Zero;
    return;
  }

  if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
    APInt Val = CI->getValue().zextOrTrunc(BitWidth);
    DestLOI.NumSignBits = Val.getNumSignBits();
    DestLOI.KnownZero = ~Val;
    DestLOI.KnownOne = Val;
  } else {
    assert(ValueMap.count(V) && "V should have been placed in ValueMap when its"
                                "CopyToReg node was created.");
    unsigned SrcReg = ValueMap[V];
    if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) {
      DestLOI.IsValid = false;
      return;
    }
    const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth);
    if (!SrcLOI) {
      DestLOI.IsValid = false;
      return;
    }
    DestLOI = *SrcLOI;
  }

  assert(DestLOI.KnownZero.getBitWidth() == BitWidth &&
         DestLOI.KnownOne.getBitWidth() == BitWidth &&
         "Masks should have the same bit width as the type.");

  for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) {
    Value *V = PN->getIncomingValue(i);
    if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
      DestLOI.NumSignBits = 1;
      APInt Zero(BitWidth, 0);
      DestLOI.KnownZero = Zero;
      DestLOI.KnownOne = Zero;
      return;
    }

    if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
      APInt Val = CI->getValue().zextOrTrunc(BitWidth);
      DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, Val.getNumSignBits());
      DestLOI.KnownZero &= ~Val;
      DestLOI.KnownOne &= Val;
      continue;
    }

    assert(ValueMap.count(V) && "V should have been placed in ValueMap when "
                                "its CopyToReg node was created.");
    unsigned SrcReg = ValueMap[V];
    if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) {
      DestLOI.IsValid = false;
      return;
    }
    const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth);
    if (!SrcLOI) {
      DestLOI.IsValid = false;
      return;
    }
    DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, SrcLOI->NumSignBits);
    DestLOI.KnownZero &= SrcLOI->KnownZero;
    DestLOI.KnownOne &= SrcLOI->KnownOne;
  }
}
Esempio n. 5
0
llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nesttype, bool ismain)
{
    if (Logger::enabled())
        Logger::println("DtoFunctionType(%s)", type->toChars());
    LOG_SCOPE

    // sanity check
    assert(type->ty == Tfunction);
    TypeFunction* f = (TypeFunction*)type;

    TargetABI* abi = (f->linkage == LINKintrinsic ? TargetABI::getIntrinsic() : gABI);
    // Tell the ABI we're resolving a new function type
    abi->newFunctionType(f);

    // Do not modify f->fty yet; this function may be called recursively if any
    // of the argument types refer to this type.
    IrFuncTy fty;

    // llvm idx counter
    size_t lidx = 0;

    // main needs a little special handling
    if (ismain)
    {
        fty.ret = new IrFuncTyArg(Type::tint32, false);
    }
    // sane return value
    else
    {
        Type* rt = f->next;
        unsigned a = 0;
        // sret return
        if (abi->returnInArg(f))
        {
            fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias | NoCapture);
            rt = Type::tvoid;
            lidx++;
        }
        // sext/zext return
        else
        {
            Type *t = rt;
#if DMDV2
            if (f->isref)
                t = t->pointerTo();
#endif
            if (unsigned se = DtoShouldExtend(t))
                a = se;
        }
#if DMDV2
        fty.ret = new IrFuncTyArg(rt, f->isref, a);
#else
        fty.ret = new IrFuncTyArg(rt, false, a);
#endif
    }
    lidx++;

    // member functions
    if (thistype)
    {
        fty.arg_this = new IrFuncTyArg(thistype, thistype->toBasetype()->ty == Tstruct);
        lidx++;
    }

    // and nested functions
    else if (nesttype)
    {
        fty.arg_nest = new IrFuncTyArg(nesttype, false);
        lidx++;
    }

    // vararg functions are special too
    if (f->varargs)
    {
        if (f->linkage == LINKd)
        {
            // d style with hidden args
            // 2 (array) is handled by the frontend
            if (f->varargs == 1)
            {
                // _arguments
                fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
                lidx++;
                // _argptr
                fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false, NoAlias | NoCapture);
                lidx++;
            }
        }
        else if (f->linkage == LINKc)
        {
            fty.c_vararg = true;
        }
        else
        {
            type->error(0, "invalid linkage for variadic function");
            fatal();
        }
    }

    // if this _Dmain() doesn't have an argument, we force it to have one
    int nargs = Parameter::dim(f->parameters);

    if (ismain && nargs == 0)
    {
        Type* mainargs = Type::tchar->arrayOf()->arrayOf();
        fty.args.push_back(new IrFuncTyArg(mainargs, false));
        lidx++;
    }
    // add explicit parameters
    else for (int i = 0; i < nargs; i++)
    {
        // get argument
        Parameter* arg = Parameter::getNth(f->parameters, i);

        // reference semantics? ref, out and d1 static arrays are
        bool byref = arg->storageClass & (STCref|STCout);
#if !SARRAYVALUE
        byref = byref || (arg->type->toBasetype()->ty == Tsarray);
#endif

        Type* argtype = arg->type;
        unsigned a = 0;

        // handle lazy args
        if (arg->storageClass & STClazy)
        {
            Logger::println("lazy param");
            TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
            TypeDelegate *ltd = new TypeDelegate(ltf);
            argtype = ltd;
        }
        // byval
        else if (abi->passByVal(byref ? argtype->pointerTo() : argtype))
        {
            if (!byref) a |= llvm::Attribute::ByVal;
            byref = true;
        }
        // sext/zext
        else if (!byref)
        {
            a |= DtoShouldExtend(argtype);
        }

        fty.args.push_back(new IrFuncTyArg(argtype, byref, a));
        lidx++;
    }

    // Now we can modify f->fty safely.
    f->fty = fty;

    // let the abi rewrite the types as necesary
    abi->rewriteFunctionType(f);

    // Tell the ABI we're done with this function type
    abi->doneWithFunctionType();

    // build the function type
    std::vector<LLType*> argtypes;
    argtypes.reserve(lidx);

    if (f->fty.arg_sret) argtypes.push_back(f->fty.arg_sret->ltype);
    if (f->fty.arg_this) argtypes.push_back(f->fty.arg_this->ltype);
    if (f->fty.arg_nest) argtypes.push_back(f->fty.arg_nest->ltype);
    if (f->fty.arg_arguments) argtypes.push_back(f->fty.arg_arguments->ltype);
    if (f->fty.arg_argptr) argtypes.push_back(f->fty.arg_argptr->ltype);

    size_t beg = argtypes.size();
    size_t nargs2 = f->fty.args.size();
    for (size_t i = 0; i < nargs2; i++)
    {
        argtypes.push_back(f->fty.args[i]->ltype);
    }

    // reverse params?
    if (f->fty.reverseParams && nargs2 > 1)
    {
        std::reverse(argtypes.begin() + beg, argtypes.end());
    }

    LLFunctionType* functype = LLFunctionType::get(f->fty.ret->ltype, argtypes, f->fty.c_vararg);

    Logger::cout() << "Final function type: " << *functype << "\n";

    return functype;
}
Esempio n. 6
0
Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, 
                       DeclName Member, ConstraintLocator *locator,
                       ArrayRef<TypeVariableType *> typeVars)
  : Kind(Kind), HasRestriction(false), HasFix(false), IsActive(false),
    RememberChoice(false), IsFavored(false), NumTypeVariables(typeVars.size()),
    Types { First, Second, Member }, Locator(locator)
{
  switch (Kind) {
  case ConstraintKind::Bind:
  case ConstraintKind::Equal:
  case ConstraintKind::BindParam:
  case ConstraintKind::Subtype:
  case ConstraintKind::Conversion:
  case ConstraintKind::ExplicitConversion:
  case ConstraintKind::ArgumentConversion:
  case ConstraintKind::ArgumentTupleConversion:
  case ConstraintKind::OperatorArgumentTupleConversion:
  case ConstraintKind::OperatorArgumentConversion:
  case ConstraintKind::ConformsTo:
  case ConstraintKind::CheckedCast:
  case ConstraintKind::SelfObjectOfProtocol:
  case ConstraintKind::DynamicTypeOf:
  case ConstraintKind::OptionalObject:
    assert(!First.isNull());
    assert(!Second.isNull());
    assert(!Member && "Relational constraint cannot have a member");
    break;
  case ConstraintKind::ApplicableFunction:
    assert(First->is<FunctionType>()
           && "The left-hand side type should be a function type");
    assert(!Member && "Relational constraint cannot have a member");
    break;

  case ConstraintKind::TypeMember:
  case ConstraintKind::ValueMember:
  case ConstraintKind::UnresolvedValueMember:
    assert(Member && "Member constraint has no member");
    break;

  case ConstraintKind::Archetype:
  case ConstraintKind::Class:
  case ConstraintKind::BridgedToObjectiveC:
    assert(!Member && "Type property cannot have a member");
    assert(Second.isNull() && "Type property with second type");
    break;

  case ConstraintKind::Defaultable:
    assert(!First.isNull());
    assert(!Second.isNull());
    assert(!Member && "Defaultable constraint cannot have a member");
    break;

  case ConstraintKind::BindOverload:
    llvm_unreachable("Wrong constructor for overload binding constraint");

  case ConstraintKind::Disjunction:
    llvm_unreachable("Disjunction constraints should use create()");
  }

  std::copy(typeVars.begin(), typeVars.end(), getTypeVariablesBuffer().begin());
}
string halide_type_to_tiramisu_type_str(Type type)
{
    if (type.is_uint())
    {
        if (type.bits() == 8)
        {
            return "tiramisu::p_uint8";
        }
        else if (type.bits() == 16)
        {
            return "tiramisu::p_uint16";
        }
        else if (type.bits() == 32)
        {
            return "tiramisu::p_uint32";
        }
        else
        {
            return "tiramisu::p_uint64";
        }
    }
    else if (type.is_int())
    {
        if (type.bits() == 8)
        {
            return "tiramisu::p_int8";
        }
        else if (type.bits() == 16)
        {
            return "tiramisu::p_int16";
        }
        else if (type.bits() == 32)
        {
            return "tiramisu::p_int32";
        }
        else
        {
            return "tiramisu::p_int64";
        }
    }
    else if (type.is_float())
    {
        if (type.bits() == 32)
        {
            return "tiramisu::p_float32";
        }
        else if (type.bits() == 64)
        {
            return "tiramisu::p_float64";
        }
        else
        {
            tiramisu::error("Floats other than 32 and 64 bits are not suppored in Tiramisu.", true);
        }
    }
    else if (type.is_bool())
    {
        return "tiramisu::p_boolean";
    }
    else
    {
        tiramisu::error("Halide type cannot be translated to Tiramisu type.", true);
    }
    return "tiramisu::p_none";
}
Esempio n. 8
0
File: typinf.c Progetto: venix1/dmd
void TypeInfoStructDeclaration::toDt(dt_t **pdt)
{
    //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());

    unsigned offset = Type::typeinfostruct->structsize;

    dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct
    dtsize_t(pdt, 0);                        // monitor

    assert(tinfo->ty == Tstruct);

    TypeStruct *tc = (TypeStruct *)tinfo;
    StructDeclaration *sd = tc->sym;

    /* Put out:
     *  char[] name;
     *  void[] init;
     *  hash_t function(in void*) xtoHash;
     *  bool function(in void*, in void*) xopEquals;
     *  int function(in void*, in void*) xopCmp;
     *  string function(const(void)*) xtoString;
     *  uint m_flags;
     *  xgetMembers;
     *  xdtor;
     *  xpostblit;
     *  uint m_align;
     *  version (X86_64)
     *      TypeInfo m_arg1;
     *      TypeInfo m_arg2;
     *
     *  name[]
     */

    const char *name = sd->toPrettyChars();
    size_t namelen = strlen(name);
    dtsize_t(pdt, namelen);
    //dtabytes(pdt, TYnptr, 0, namelen + 1, name);
    dtxoff(pdt, toSymbol(), offset, TYnptr);
    offset += namelen + 1;

    // void[] init;
    dtsize_t(pdt, sd->structsize);       // init.length
    if (sd->zeroInit)
        dtsize_t(pdt, 0);                // NULL for 0 initialization
    else
        dtxoff(pdt, sd->toInitializer(), 0, TYnptr);    // init.ptr

    FuncDeclaration *fd;
    FuncDeclaration *fdx;
    Dsymbol *s;

    static TypeFunction *tftohash;
    static TypeFunction *tftostring;

    if (!tftohash)
    {
        Scope sc;

        /* const hash_t toHash();
         */
        tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
        tftohash->mod = MODconst;
        tftohash = (TypeFunction *)tftohash->semantic(0, &sc);

        tftostring = new TypeFunction(NULL, Type::tchar->invariantOf()->arrayOf(), 0, LINKd);
        tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
    }

    TypeFunction *tfcmpptr;
    {
        Scope sc;

        /* const int opCmp(ref const KeyType s);
         */
        Parameters *arguments = new Parameters;
#if STRUCTTHISREF
        // arg type is ref const T
        Parameter *arg = new Parameter(STCref, tc->constOf(), NULL, NULL);
#else
        // arg type is const T*
        Parameter *arg = new Parameter(STCin, tc->pointerTo(), NULL, NULL);
#endif

        arguments->push(arg);
        tfcmpptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
        tfcmpptr->mod = MODconst;
        tfcmpptr = (TypeFunction *)tfcmpptr->semantic(0, &sc);
    }

    s = search_function(sd, Id::tohash);
    fdx = s ? s->isFuncDeclaration() : NULL;
    if (fdx)
    {   fd = fdx->overloadExactMatch(tftohash);
        if (fd)
        {
            dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
            TypeFunction *tf = (TypeFunction *)fd->type;
            assert(tf->ty == Tfunction);
            if (global.params.warnings)
            {
                /* I'm a little unsure this is the right way to do it. Perhaps a better
                 * way would to automatically add these attributes to any struct member
                 * function with the name "toHash".
                 * So I'm leaving this here as an experiment for the moment.
                 */
                if (!tf->isnothrow || tf->trust == TRUSTsystem /*|| tf->purity == PUREimpure*/)
                {   warning(fd->loc, "toHash() must be declared as extern (D) uint toHash() const nothrow @safe, not %s", tf->toChars());
                    if (global.params.warnings == 1)
                        global.errors++;
                }
            }
        }
        else
        {
            //fdx->error("must be declared as extern (D) uint toHash()");
            dtsize_t(pdt, 0);
        }
    }
    else
        dtsize_t(pdt, 0);

    if (sd->xeq)
        dtxoff(pdt, sd->xeq->toSymbol(), 0, TYnptr);
    else
        dtsize_t(pdt, 0);

    s = search_function(sd, Id::cmp);
    fdx = s ? s->isFuncDeclaration() : NULL;
    if (fdx)
    {
        //printf("test1 %s, %s, %s\n", fdx->toChars(), fdx->type->toChars(), tfeqptr->toChars());
        fd = fdx->overloadExactMatch(tfcmpptr);
        if (fd)
        {   dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
            //printf("test2\n");
        }
        else
            //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
            dtsize_t(pdt, 0);
    }
    else
        dtsize_t(pdt, 0);

    s = search_function(sd, Id::tostring);
    fdx = s ? s->isFuncDeclaration() : NULL;
    if (fdx)
    {   fd = fdx->overloadExactMatch(tftostring);
        if (fd)
            dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
        else
            //fdx->error("must be declared as extern (D) char[] toString()");
            dtsize_t(pdt, 0);
    }
    else
        dtsize_t(pdt, 0);

    // uint m_flags;
    dtsize_t(pdt, tc->hasPointers());

#if DMDV2
    // xgetMembers
    FuncDeclaration *sgetmembers = sd->findGetMembers();
    if (sgetmembers)
        dtxoff(pdt, sgetmembers->toSymbol(), 0, TYnptr);
    else
        dtsize_t(pdt, 0);                        // xgetMembers

    // xdtor
    FuncDeclaration *sdtor = sd->dtor;
    if (sdtor)
        dtxoff(pdt, sdtor->toSymbol(), 0, TYnptr);
    else
        dtsize_t(pdt, 0);                        // xdtor

    // xpostblit
    FuncDeclaration *spostblit = sd->postblit;
    if (spostblit && !(spostblit->storage_class & STCdisable))
        dtxoff(pdt, spostblit->toSymbol(), 0, TYnptr);
    else
        dtsize_t(pdt, 0);                        // xpostblit
#endif

    // uint m_align;
    dtsize_t(pdt, tc->alignsize());

    if (global.params.is64bit)
    {
        TypeTuple *tup = tc->toArgTypes();
        assert(tup->arguments->dim <= 2);
        for (size_t i = 0; i < 2; i++)
        {
            if (i < tup->arguments->dim)
            {
                Type *targ = (tup->arguments->tdata()[i])->type;
                targ = targ->merge();
                targ->getTypeInfo(NULL);
                dtxoff(pdt, targ->vtinfo->toSymbol(), 0, TYnptr);       // m_argi
            }
            else
                dtsize_t(pdt, 0);                    // m_argi
        }
    }

    // name[]
    dtnbytes(pdt, namelen + 1, name);
}
Esempio n. 9
0
File: typinf.c Progetto: venix1/dmd
Expression *createTypeInfoArray(Scope *sc, Expression *exps[], unsigned dim)
{
#if 1
    /* Get the corresponding TypeInfo_Tuple and
     * point at its elements[].
     */

    /* Create the TypeTuple corresponding to the types of args[]
     */
    Parameters *args = new Parameters;
    args->setDim(dim);
    for (size_t i = 0; i < dim; i++)
    {   Parameter *arg = new Parameter(STCin, exps[i]->type, NULL, NULL);
        args->tdata()[i] = arg;
    }
    TypeTuple *tup = new TypeTuple(args);
    Expression *e = tup->getTypeInfo(sc);
    e = e->optimize(WANTvalue);
    assert(e->op == TOKsymoff);         // should be SymOffExp

#if BREAKABI
    /*
     * Should just pass a reference to TypeInfo_Tuple instead,
     * but that would require existing code to be recompiled.
     * Source compatibility can be maintained by computing _arguments[]
     * at the start of the called function by offseting into the
     * TypeInfo_Tuple reference.
     */

#else
    // Advance to elements[] member of TypeInfo_Tuple
    SymOffExp *se = (SymOffExp *)e;
    se->offset += PTRSIZE + PTRSIZE;

    // Set type to TypeInfo[]*
    se->type = Type::typeinfo->type->arrayOf()->pointerTo();

    // Indirect to get the _arguments[] value
    e = new PtrExp(0, se);
    e->type = se->type->next;
#endif
    return e;
#else
    /* Improvements:
     * 1) create an array literal instead,
     * as it would eliminate the extra dereference of loading the
     * static variable.
     */

    ArrayInitializer *ai = new ArrayInitializer(0);
    VarDeclaration *v;
    Type *t;
    Expression *e;
    OutBuffer buf;
    Identifier *id;
    char *name;

    // Generate identifier for _arguments[]
    buf.writestring("_arguments_");
    for (int i = 0; i < dim; i++)
    {   t = exps[i]->type;
        t->toDecoBuffer(&buf);
    }
    buf.writeByte(0);
    id = Lexer::idPool((char *)buf.data);

    Module *m = sc->module;
    Dsymbol *s = m->symtab->lookup(id);

    if (s && s->parent == m)
    {   // Use existing one
        v = s->isVarDeclaration();
        assert(v);
    }
    else
    {   // Generate new one

        for (int i = 0; i < dim; i++)
        {   t = exps[i]->type;
            e = t->getTypeInfo(sc);
            ai->addInit(new IntegerExp(i), new ExpInitializer(0, e));
        }

        t = Type::typeinfo->type->arrayOf();
        ai->type = t;
        v = new VarDeclaration(0, t, id, ai);
        m->members->push(v);
        m->symtabInsert(v);
        sc = sc->push();
        sc->linkage = LINKc;
        sc->stc = STCstatic | STCcomdat;
        ai->semantic(sc, t);
        v->semantic(sc);
        v->parent = m;
        sc = sc->pop();
    }
    e = new VarExp(0, v);
    e = e->semantic(sc);
    return e;
#endif
}
Esempio n. 10
0
bool TypeChecker::checkGenericArguments(DeclContext *dc, SourceLoc loc,
                                        SourceLoc noteLoc,
                                        Type owner,
                                        GenericSignature *genericSig,
                                        ArrayRef<Type> genericArgs) {
  // Form the set of generic substitutions required
  TypeSubstitutionMap substitutions;

  auto genericParams = genericSig->getGenericParams();

  unsigned count = 0;

  // If the type is nested inside a generic function, skip
  // substitutions from the outer context.
  unsigned start = (genericParams.size() - genericArgs.size());

  for (auto gp : genericParams) {
    if (count >= start) {
      auto gpTy = gp->getCanonicalType()->castTo<GenericTypeParamType>();
      substitutions[gpTy] = genericArgs[count - start];
    }

    count++;
  }

  // The number of generic type arguments being bound must be equal to the
  // total number of generic parameters in the current generic type context.
  assert(count - start == genericArgs.size());

  // Check each of the requirements.
  Module *module = dc->getParentModule();
  for (const auto &req : genericSig->getRequirements()) {
    Type firstType = req.getFirstType().subst(module, substitutions,
                                              SubstFlags::IgnoreMissing);
    if (firstType.isNull()) {
      // Another requirement will fail later; just continue.
      continue;
    }

    Type secondType = req.getSecondType();
    if (secondType) {
      secondType = secondType.subst(module, substitutions,
                                    SubstFlags::IgnoreMissing);
      if (secondType.isNull()) {
        // Another requirement will fail later; just continue.
        continue;
      }
    }

    switch (req.getKind()) {
    case RequirementKind::Conformance: {
      // Protocol conformance requirements.
      auto proto = secondType->castTo<ProtocolType>();
      // FIXME: This should track whether this should result in a private
      // or non-private dependency.
      // FIXME: Do we really need "used" at this point?
      // FIXME: Poor location information. How much better can we do here?
      if (!conformsToProtocol(firstType, proto->getDecl(), dc,
                              ConformanceCheckFlags::Used, nullptr, loc)) {
        return true;
      }

      continue;
    }

    case RequirementKind::Superclass:
      // Superclass requirements.
      if (!isSubtypeOf(firstType, secondType, dc)) {
        // FIXME: Poor source-location information.
        diagnose(loc, diag::type_does_not_inherit, owner, firstType,
                 secondType);

        diagnose(noteLoc, diag::type_does_not_inherit_requirement,
                 req.getFirstType(), req.getSecondType(),
                 gatherGenericParamBindingsText(
                   {req.getFirstType(), req.getSecondType()},
                   genericParams, substitutions));
        return true;
      }
      continue;

    case RequirementKind::SameType:
      if (!firstType->isEqual(secondType)) {
        // FIXME: Better location info for both diagnostics.
        diagnose(loc, diag::types_not_equal, owner, firstType, secondType);

        diagnose(noteLoc, diag::types_not_equal_requirement,
                 req.getFirstType(), req.getSecondType(),
                 gatherGenericParamBindingsText(
                   {req.getFirstType(), req.getSecondType()},
                   genericParams, substitutions));
        return true;
      }
      continue;
      
    case RequirementKind::WitnessMarker:
      continue;
    }
  }

  return false;
}
Esempio n. 11
0
File: JIT.cpp Progetto: pshung/DBT
/// run - Start execution with the specified function and arguments.
///
GenericValue JIT::runFunction(Function *F,
                              const std::vector<GenericValue> &ArgValues) {
    assert(F && "Function *F was null at entry to run()");

    void *FPtr = getPointerToFunction(F);
    assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
    FunctionType *FTy = F->getFunctionType();
    Type *RetTy = FTy->getReturnType();

    assert((FTy->getNumParams() == ArgValues.size() ||
            (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
           "Wrong number of arguments passed into function!");
    assert(FTy->getNumParams() == ArgValues.size() &&
           "This doesn't support passing arguments through varargs (yet)!");

    // Handle some common cases first.  These cases correspond to common `main'
    // prototypes.
    if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
        switch (ArgValues.size()) {
        case 3:
            if (FTy->getParamType(0)->isIntegerTy(32) &&
                    FTy->getParamType(1)->isPointerTy() &&
                    FTy->getParamType(2)->isPointerTy()) {
                int (*PF)(int, char **, const char **) =
                    (int(*)(int, char **, const char **))(intptr_t)FPtr;

                // Call the function.
                GenericValue rv;
                rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                         (char **)GVTOP(ArgValues[1]),
                                         (const char **)GVTOP(ArgValues[2])));
                return rv;
            }
            break;
        case 2:
            if (FTy->getParamType(0)->isIntegerTy(32) &&
                    FTy->getParamType(1)->isPointerTy()) {
                int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;

                // Call the function.
                GenericValue rv;
                rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                         (char **)GVTOP(ArgValues[1])));
                return rv;
            }
            break;
        case 1:
            if (FTy->getParamType(0)->isIntegerTy(32)) {
                GenericValue rv;
                int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
                rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
                return rv;
            }
            if (FTy->getParamType(0)->isPointerTy()) {
                GenericValue rv;
                int (*PF)(char *) = (int(*)(char *))(intptr_t)FPtr;
                rv.IntVal = APInt(32, PF((char*)GVTOP(ArgValues[0])));
                return rv;
            }
            break;
        }
    }

    // Handle cases where no arguments are passed first.
    if (ArgValues.empty()) {
        GenericValue rv;
        switch (RetTy->getTypeID()) {
        default:
            llvm_unreachable("Unknown return type for function call!");
        case Type::IntegerTyID: {
            unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
            if (BitWidth == 1)
                rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
            else if (BitWidth <= 8)
                rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
            else if (BitWidth <= 16)
                rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
            else if (BitWidth <= 32)
                rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
            else if (BitWidth <= 64)
                rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
            else
                llvm_unreachable("Integer types > 64 bits not supported");
            return rv;
        }
        case Type::VoidTyID:
            rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
            return rv;
        case Type::FloatTyID:
            rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
            return rv;
        case Type::DoubleTyID:
            rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
            return rv;
        case Type::X86_FP80TyID:
        case Type::FP128TyID:
        case Type::PPC_FP128TyID:
            llvm_unreachable("long double not supported yet");
        case Type::PointerTyID:
            return PTOGV(((void*(*)())(intptr_t)FPtr)());
        }
    }

    // Okay, this is not one of our quick and easy cases.  Because we don't have a
    // full FFI, we have to codegen a nullary stub function that just calls the
    // function we are interested in, passing in constants for all of the
    // arguments.  Make this function and return.

    // First, create the function.
    FunctionType *STy=FunctionType::get(RetTy, false);
    Function *Stub = Function::Create(STy, Function::InternalLinkage, "",
                                      F->getParent());

    // Insert a basic block.
    BasicBlock *StubBB = BasicBlock::Create(F->getContext(), "", Stub);

    // Convert all of the GenericValue arguments over to constants.  Note that we
    // currently don't support varargs.
    SmallVector<Value*, 8> Args;
    for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) {
        Constant *C = 0;
        Type *ArgTy = FTy->getParamType(i);
        const GenericValue &AV = ArgValues[i];
        switch (ArgTy->getTypeID()) {
        default:
            llvm_unreachable("Unknown argument type for function call!");
        case Type::IntegerTyID:
            C = ConstantInt::get(F->getContext(), AV.IntVal);
            break;
        case Type::FloatTyID:
            C = ConstantFP::get(F->getContext(), APFloat(AV.FloatVal));
            break;
        case Type::DoubleTyID:
            C = ConstantFP::get(F->getContext(), APFloat(AV.DoubleVal));
            break;
        case Type::PPC_FP128TyID:
        case Type::X86_FP80TyID:
        case Type::FP128TyID:
            C = ConstantFP::get(F->getContext(), APFloat(AV.IntVal));
            break;
        case Type::PointerTyID:
            void *ArgPtr = GVTOP(AV);
            if (sizeof(void*) == 4)
                C = ConstantInt::get(Type::getInt32Ty(F->getContext()),
                                     (int)(intptr_t)ArgPtr);
            else
                C = ConstantInt::get(Type::getInt64Ty(F->getContext()),
                                     (intptr_t)ArgPtr);
            // Cast the integer to pointer
            C = ConstantExpr::getIntToPtr(C, ArgTy);
            break;
        }
        Args.push_back(C);
    }

    CallInst *TheCall = CallInst::Create(F, Args, "", StubBB);
    TheCall->setCallingConv(F->getCallingConv());
    TheCall->setTailCall();
    if (!TheCall->getType()->isVoidTy())
        // Return result of the call.
        ReturnInst::Create(F->getContext(), TheCall, StubBB);
    else
        ReturnInst::Create(F->getContext(), StubBB);           // Just return void.

    // Finally, call our nullary stub function.
    GenericValue Result = runFunction(Stub, std::vector<GenericValue>());
    // Erase it, since no other function can have a reference to it.
    Stub->eraseFromParent();
    // And return the result.
    return Result;
}
Value* AMDGPUCodeGenPrepare::expandDivRem32(IRBuilder<> &Builder,
                                            BinaryOperator &I,
                                            Value *Num, Value *Den) const {
  Instruction::BinaryOps Opc = I.getOpcode();
  assert(Opc == Instruction::URem || Opc == Instruction::UDiv ||
         Opc == Instruction::SRem || Opc == Instruction::SDiv);

  FastMathFlags FMF;
  FMF.setFast();
  Builder.setFastMathFlags(FMF);

  if (isa<Constant>(Den))
    return nullptr; // Keep it for optimization

  bool IsDiv = Opc == Instruction::UDiv || Opc == Instruction::SDiv;
  bool IsSigned = Opc == Instruction::SRem || Opc == Instruction::SDiv;

  Type *Ty = Num->getType();
  Type *I32Ty = Builder.getInt32Ty();
  Type *F32Ty = Builder.getFloatTy();

  if (Ty->getScalarSizeInBits() < 32) {
    if (IsSigned) {
      Num = Builder.CreateSExt(Num, I32Ty);
      Den = Builder.CreateSExt(Den, I32Ty);
    } else {
      Num = Builder.CreateZExt(Num, I32Ty);
      Den = Builder.CreateZExt(Den, I32Ty);
    }
  }

  if (Value *Res = expandDivRem24(Builder, I, Num, Den, IsDiv, IsSigned)) {
    Res = Builder.CreateTrunc(Res, Ty);
    return Res;
  }

  ConstantInt *Zero = Builder.getInt32(0);
  ConstantInt *One = Builder.getInt32(1);
  ConstantInt *MinusOne = Builder.getInt32(~0);

  Value *Sign = nullptr;
  if (IsSigned) {
    ConstantInt *K31 = Builder.getInt32(31);
    Value *LHSign = Builder.CreateAShr(Num, K31);
    Value *RHSign = Builder.CreateAShr(Den, K31);
    // Remainder sign is the same as LHS
    Sign = IsDiv ? Builder.CreateXor(LHSign, RHSign) : LHSign;

    Num = Builder.CreateAdd(Num, LHSign);
    Den = Builder.CreateAdd(Den, RHSign);

    Num = Builder.CreateXor(Num, LHSign);
    Den = Builder.CreateXor(Den, RHSign);
  }

  // RCP =  URECIP(Den) = 2^32 / Den + e
  // e is rounding error.
  Value *DEN_F32 = Builder.CreateUIToFP(Den, F32Ty);
  Value *RCP_F32 = Builder.CreateFDiv(ConstantFP::get(F32Ty, 1.0), DEN_F32);
  Constant *UINT_MAX_PLUS_1 = ConstantFP::get(F32Ty, BitsToFloat(0x4f800000));
  Value *RCP_SCALE = Builder.CreateFMul(RCP_F32, UINT_MAX_PLUS_1);
  Value *RCP = Builder.CreateFPToUI(RCP_SCALE, I32Ty);

  // RCP_LO, RCP_HI = mul(RCP, Den) */
  Value *RCP_LO, *RCP_HI;
  std::tie(RCP_LO, RCP_HI) = getMul64(Builder, RCP, Den);

  // NEG_RCP_LO = -RCP_LO
  Value *NEG_RCP_LO = Builder.CreateNeg(RCP_LO);

  // ABS_RCP_LO = (RCP_HI == 0 ? NEG_RCP_LO : RCP_LO)
  Value *RCP_HI_0_CC = Builder.CreateICmpEQ(RCP_HI, Zero);
  Value *ABS_RCP_LO = Builder.CreateSelect(RCP_HI_0_CC, NEG_RCP_LO, RCP_LO);

  // Calculate the rounding error from the URECIP instruction
  // E = mulhu(ABS_RCP_LO, RCP)
  Value *E = getMulHu(Builder, ABS_RCP_LO, RCP);

  // RCP_A_E = RCP + E
  Value *RCP_A_E = Builder.CreateAdd(RCP, E);

  // RCP_S_E = RCP - E
  Value *RCP_S_E = Builder.CreateSub(RCP, E);

  // Tmp0 = (RCP_HI == 0 ? RCP_A_E : RCP_SUB_E)
  Value *Tmp0 = Builder.CreateSelect(RCP_HI_0_CC, RCP_A_E, RCP_S_E);

  // Quotient = mulhu(Tmp0, Num)
  Value *Quotient = getMulHu(Builder, Tmp0, Num);

  // Num_S_Remainder = Quotient * Den
  Value *Num_S_Remainder = Builder.CreateMul(Quotient, Den);

  // Remainder = Num - Num_S_Remainder
  Value *Remainder = Builder.CreateSub(Num, Num_S_Remainder);

  // Remainder_GE_Den = (Remainder >= Den ? -1 : 0)
  Value *Rem_GE_Den_CC = Builder.CreateICmpUGE(Remainder, Den);
  Value *Remainder_GE_Den = Builder.CreateSelect(Rem_GE_Den_CC, MinusOne, Zero);

  // Remainder_GE_Zero = (Num >= Num_S_Remainder ? -1 : 0)
  Value *Num_GE_Num_S_Rem_CC = Builder.CreateICmpUGE(Num, Num_S_Remainder);
  Value *Remainder_GE_Zero = Builder.CreateSelect(Num_GE_Num_S_Rem_CC,
                                                  MinusOne, Zero);

  // Tmp1 = Remainder_GE_Den & Remainder_GE_Zero
  Value *Tmp1 = Builder.CreateAnd(Remainder_GE_Den, Remainder_GE_Zero);
  Value *Tmp1_0_CC = Builder.CreateICmpEQ(Tmp1, Zero);

  Value *Res;
  if (IsDiv) {
    // Quotient_A_One = Quotient + 1
    Value *Quotient_A_One = Builder.CreateAdd(Quotient, One);

    // Quotient_S_One = Quotient - 1
    Value *Quotient_S_One = Builder.CreateSub(Quotient, One);

    // Div = (Tmp1 == 0 ? Quotient : Quotient_A_One)
    Value *Div = Builder.CreateSelect(Tmp1_0_CC, Quotient, Quotient_A_One);

    // Div = (Remainder_GE_Zero == 0 ? Quotient_S_One : Div)
    Res = Builder.CreateSelect(Num_GE_Num_S_Rem_CC, Div, Quotient_S_One);
  } else {
    // Remainder_S_Den = Remainder - Den
    Value *Remainder_S_Den = Builder.CreateSub(Remainder, Den);

    // Remainder_A_Den = Remainder + Den
    Value *Remainder_A_Den = Builder.CreateAdd(Remainder, Den);

    // Rem = (Tmp1 == 0 ? Remainder : Remainder_S_Den)
    Value *Rem = Builder.CreateSelect(Tmp1_0_CC, Remainder, Remainder_S_Den);

    // Rem = (Remainder_GE_Zero == 0 ? Remainder_A_Den : Rem)
    Res = Builder.CreateSelect(Num_GE_Num_S_Rem_CC, Rem, Remainder_A_Den);
  }

  if (IsSigned) {
    Res = Builder.CreateXor(Res, Sign);
    Res = Builder.CreateSub(Res, Sign);
  }

  Res = Builder.CreateTrunc(Res, Ty);

  return Res;
}
// Insert an intrinsic for fast fdiv for safe math situations where we can
// reduce precision. Leave fdiv for situations where the generic node is
// expected to be optimized.
bool AMDGPUCodeGenPrepare::visitFDiv(BinaryOperator &FDiv) {
  Type *Ty = FDiv.getType();

  if (!Ty->getScalarType()->isFloatTy())
    return false;

  MDNode *FPMath = FDiv.getMetadata(LLVMContext::MD_fpmath);
  if (!FPMath)
    return false;

  const FPMathOperator *FPOp = cast<const FPMathOperator>(&FDiv);
  float ULP = FPOp->getFPAccuracy();
  if (ULP < 2.5f)
    return false;

  FastMathFlags FMF = FPOp->getFastMathFlags();
  bool UnsafeDiv = HasUnsafeFPMath || FMF.isFast() ||
                                      FMF.allowReciprocal();

  // With UnsafeDiv node will be optimized to just rcp and mul.
  if (UnsafeDiv)
    return false;

  IRBuilder<> Builder(FDiv.getParent(), std::next(FDiv.getIterator()), FPMath);
  Builder.setFastMathFlags(FMF);
  Builder.SetCurrentDebugLocation(FDiv.getDebugLoc());

  Function *Decl = Intrinsic::getDeclaration(Mod, Intrinsic::amdgcn_fdiv_fast);

  Value *Num = FDiv.getOperand(0);
  Value *Den = FDiv.getOperand(1);

  Value *NewFDiv = nullptr;

  bool HasDenormals = ST->hasFP32Denormals();
  if (VectorType *VT = dyn_cast<VectorType>(Ty)) {
    NewFDiv = UndefValue::get(VT);

    // FIXME: Doesn't do the right thing for cases where the vector is partially
    // constant. This works when the scalarizer pass is run first.
    for (unsigned I = 0, E = VT->getNumElements(); I != E; ++I) {
      Value *NumEltI = Builder.CreateExtractElement(Num, I);
      Value *DenEltI = Builder.CreateExtractElement(Den, I);
      Value *NewElt;

      if (shouldKeepFDivF32(NumEltI, UnsafeDiv, HasDenormals)) {
        NewElt = Builder.CreateFDiv(NumEltI, DenEltI);
      } else {
        NewElt = Builder.CreateCall(Decl, { NumEltI, DenEltI });
      }

      NewFDiv = Builder.CreateInsertElement(NewFDiv, NewElt, I);
    }
  } else {
    if (!shouldKeepFDivF32(Num, UnsafeDiv, HasDenormals))
      NewFDiv = Builder.CreateCall(Decl, { Num, Den });
  }

  if (NewFDiv) {
    FDiv.replaceAllUsesWith(NewFDiv);
    NewFDiv->takeName(&FDiv);
    FDiv.eraseFromParent();
  }

  return !!NewFDiv;
}
Esempio n. 14
0
void TypeChecker::configureInterfaceType(AbstractFunctionDecl *func) {
  Type funcTy;
  Type initFuncTy;

  auto *sig = func->getGenericSignature();

  if (auto fn = dyn_cast<FuncDecl>(func)) {
    funcTy = fn->getBodyResultTypeLoc().getType();
    
    if (!funcTy) {
      funcTy = TupleType::getEmpty(Context);
    } else {
      funcTy = getResultType(*this, fn, funcTy);
    }

  } else if (auto ctor = dyn_cast<ConstructorDecl>(func)) {
    auto *dc = ctor->getDeclContext();

    funcTy = dc->getSelfInterfaceType();

    // Adjust result type for failability.
    if (ctor->getFailability() != OTK_None)
      funcTy = OptionalType::get(ctor->getFailability(), funcTy);

    initFuncTy = funcTy;
  } else {
    assert(isa<DestructorDecl>(func));
    funcTy = TupleType::getEmpty(Context);
  }

  auto paramLists = func->getParameterLists();
  SmallVector<ParameterList*, 4> storedParamLists;

  // FIXME: Destructors don't have the '()' pattern in their signature, so
  // paste it here.
  if (isa<DestructorDecl>(func)) {
    assert(paramLists.size() == 1 && "Only the self paramlist");
    storedParamLists.push_back(paramLists[0]);
    storedParamLists.push_back(ParameterList::createEmpty(Context));
    paramLists = storedParamLists;
  }

  bool hasSelf = func->getDeclContext()->isTypeContext();
  for (unsigned i = 0, e = paramLists.size(); i != e; ++i) {
    Type argTy;
    Type initArgTy;

    Type selfTy;
    if (i == e-1 && hasSelf) {
      selfTy = func->computeInterfaceSelfType(/*isInitializingCtor=*/false);
      // Substitute in our own 'self' parameter.

      argTy = selfTy;
      if (initFuncTy) {
        initArgTy = func->computeInterfaceSelfType(/*isInitializingCtor=*/true);
      }
    } else {
      argTy = paramLists[e - i - 1]->getInterfaceType(func);

      if (initFuncTy)
        initArgTy = argTy;
    }

    // 'throws' only applies to the innermost function.
    AnyFunctionType::ExtInfo info;
    if (i == 0 && func->hasThrows())
      info = info.withThrows();

    assert(!argTy->hasArchetype());
    assert(!funcTy->hasArchetype());
    if (initFuncTy)
      assert(!initFuncTy->hasArchetype());

    if (sig && i == e-1) {
      funcTy = GenericFunctionType::get(sig, argTy, funcTy, info);
      if (initFuncTy)
        initFuncTy = GenericFunctionType::get(sig, initArgTy, initFuncTy, info);
    } else {
      funcTy = FunctionType::get(argTy, funcTy, info);
      if (initFuncTy)
        initFuncTy = FunctionType::get(initArgTy, initFuncTy, info);
    }
  }

  // Record the interface type.
  func->setInterfaceType(funcTy);
  if (initFuncTy)
    cast<ConstructorDecl>(func)->setInitializerInterfaceType(initFuncTy);

  if (func->getGenericParams()) {
    // Collect all generic params referenced in parameter types,
    // return type or requirements.
    SmallPtrSet<GenericTypeParamDecl *, 4> referencedGenericParams;

    auto visitorFn = [&referencedGenericParams](Type t) {
      if (auto *paramTy = t->getAs<GenericTypeParamType>())
        referencedGenericParams.insert(paramTy->getDecl());
    };

    funcTy->castTo<AnyFunctionType>()->getInput().visit(visitorFn);
    funcTy->castTo<AnyFunctionType>()->getResult().visit(visitorFn);

    auto requirements = sig->getRequirements();
    for (auto req : requirements) {
      if (req.getKind() == RequirementKind::SameType) {
        // Same type requirements may allow for generic
        // inference, even if this generic parameter
        // is not mentioned in the function signature.
        // TODO: Make the test more precise.
        auto left = req.getFirstType();
        auto right = req.getSecondType();
        // For now consider any references inside requirements
        // as a possibility to infer the generic type.
        left.visit(visitorFn);
        right.visit(visitorFn);
      }
    }

    // Find the depth of the function's own generic parameters.
    unsigned fnGenericParamsDepth = func->getGenericParams()->getDepth();

    // Check that every generic parameter type from the signature is
    // among referencedArchetypes.
    for (auto *genParam : sig->getGenericParams()) {
      auto *paramDecl = genParam->getDecl();
      if (paramDecl->getDepth() != fnGenericParamsDepth)
        continue;
      if (!referencedGenericParams.count(paramDecl)) {
        // Produce an error that this generic parameter cannot be bound.
        diagnose(paramDecl->getLoc(), diag::unreferenced_generic_parameter,
                 paramDecl->getNameStr());
        func->setInvalid();
      }
    }
  }
}
/// InstCombineStoreToCast - Fold store V, (cast P) -> store (cast V), P
/// when possible.  This makes it generally easy to do alias analysis and/or
/// SROA/mem2reg of the memory object.
static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
  User *CI = cast<User>(SI.getOperand(1));
  Value *CastOp = CI->getOperand(0);

  Type *DestPTy = CI->getType()->getPointerElementType();
  PointerType *SrcTy = dyn_cast<PointerType>(CastOp->getType());
  if (!SrcTy) return nullptr;

  Type *SrcPTy = SrcTy->getElementType();

  if (!DestPTy->isIntegerTy() && !DestPTy->isPointerTy())
    return nullptr;

  /// NewGEPIndices - If SrcPTy is an aggregate type, we can emit a "noop gep"
  /// to its first element.  This allows us to handle things like:
  ///   store i32 xxx, (bitcast {foo*, float}* %P to i32*)
  /// on 32-bit hosts.
  SmallVector<Value*, 4> NewGEPIndices;

  // If the source is an array, the code below will not succeed.  Check to
  // see if a trivial 'gep P, 0, 0' will help matters.  Only do this for
  // constants.
  if (SrcPTy->isArrayTy() || SrcPTy->isStructTy()) {
    // Index through pointer.
    Constant *Zero = Constant::getNullValue(Type::getInt32Ty(SI.getContext()));
    NewGEPIndices.push_back(Zero);

    while (1) {
      if (StructType *STy = dyn_cast<StructType>(SrcPTy)) {
        if (!STy->getNumElements()) /* Struct can be empty {} */
          break;
        NewGEPIndices.push_back(Zero);
        SrcPTy = STy->getElementType(0);
      } else if (ArrayType *ATy = dyn_cast<ArrayType>(SrcPTy)) {
        NewGEPIndices.push_back(Zero);
        SrcPTy = ATy->getElementType();
      } else {
        break;
      }
    }

    SrcTy = PointerType::get(SrcPTy, SrcTy->getAddressSpace());
  }

  if (!SrcPTy->isIntegerTy() && !SrcPTy->isPointerTy())
    return nullptr;

  // If the pointers point into different address spaces don't do the
  // transformation.
  if (SrcTy->getAddressSpace() != CI->getType()->getPointerAddressSpace())
    return nullptr;

  // If the pointers point to values of different sizes don't do the
  // transformation.
  if (!IC.getDataLayout() ||
      IC.getDataLayout()->getTypeSizeInBits(SrcPTy) !=
      IC.getDataLayout()->getTypeSizeInBits(DestPTy))
    return nullptr;

  // If the pointers point to pointers to different address spaces don't do the
  // transformation. It is not safe to introduce an addrspacecast instruction in
  // this case since, depending on the target, addrspacecast may not be a no-op
  // cast.
  if (SrcPTy->isPointerTy() && DestPTy->isPointerTy() &&
      SrcPTy->getPointerAddressSpace() != DestPTy->getPointerAddressSpace())
    return nullptr;

  // Okay, we are casting from one integer or pointer type to another of
  // the same size.  Instead of casting the pointer before
  // the store, cast the value to be stored.
  Value *NewCast;
  Instruction::CastOps opcode = Instruction::BitCast;
  Type* CastSrcTy = DestPTy;
  Type* CastDstTy = SrcPTy;
  if (CastDstTy->isPointerTy()) {
    if (CastSrcTy->isIntegerTy())
      opcode = Instruction::IntToPtr;
  } else if (CastDstTy->isIntegerTy()) {
    if (CastSrcTy->isPointerTy())
      opcode = Instruction::PtrToInt;
  }

  // SIOp0 is a pointer to aggregate and this is a store to the first field,
  // emit a GEP to index into its first field.
  if (!NewGEPIndices.empty())
    CastOp = IC.Builder->CreateInBoundsGEP(CastOp, NewGEPIndices);

  Value *SIOp0 = SI.getOperand(0);
  NewCast = IC.Builder->CreateCast(opcode, SIOp0, CastDstTy,
                                   SIOp0->getName()+".c");
  SI.setOperand(0, NewCast);
  SI.setOperand(1, CastOp);
  return &SI;
}
Esempio n. 16
0
void analyzeClass(Type classType, Writer &writer){
    auto eclass = classType.eclass;
    
    writer.writeEmojicodeChar(eclass->name);
    if(eclass->superclass){
        writer.writeUInt16(eclass->superclass->index);
    }
    else { //If the eclass does not have a superclass the own index gets written
        writer.writeUInt16(eclass->index);
    }
    
    Scope objectScope(true);
    
    //Get the ID offset for this eclass by summing up all superclasses instance variable counts
    uint16_t offset = 0;
    for(Class *aClass = eclass->superclass; aClass != nullptr; aClass = aClass->superclass){
        offset += aClass->instanceVariables.size();
    }
    writer.writeUInt16(eclass->instanceVariables.size() + offset);
    
    //Number of methods inclusive superclass
    writer.writeUInt16(eclass->nextMethodVti);
    //Number of eclass methods inclusive superclass
    writer.writeUInt16(eclass->nextClassMethodVti);
    //Initializer inclusive superclass
    writer.writeByte(eclass->inheritsContructors ? 1 : 0);
    writer.writeUInt16(eclass->nextInitializerVti);
    
    writer.writeUInt16(eclass->methodList.size());
    writer.writeUInt16(eclass->initializerList.size());
    writer.writeUInt16(eclass->classMethodList.size());
    
    for (auto var : eclass->instanceVariables) {
        CompilerVariable *cv = new CompilerVariable(var->type, offset++, 1, false);
        cv->variable = var;
        objectScope.setLocalVariable(var->name, cv);
    }
    
    pushScope(&objectScope);
    
    for (auto method : eclass->methodList) {
        StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*method, writer, classType);
    }
    
    for (auto initializer : eclass->initializerList) {
        StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*initializer, writer, classType, false, initializer);
    }
    
    popScope();
    
    for (auto classMethod : eclass->classMethodList) {
        StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*classMethod, writer, classType, true);
    }
    
    if (eclass->instanceVariables.size() > 0 && eclass->initializerList.size() == 0) {
        auto str = classType.toString(typeNothingness, true);
        compilerWarning(eclass->classBegin, "Class %s defines %d instances variables but has no initializers.", str.c_str(), eclass->instanceVariables.size());
    }
    
    writer.writeUInt16(eclass->protocols().size());
    
    if (eclass->protocols().size() > 0) {
        auto biggestPlaceholder = writer.writePlaceholder<uint16_t>();
        auto smallestPlaceholder = writer.writePlaceholder<uint16_t>();

        uint_fast16_t smallestProtocolIndex = UINT_FAST16_MAX;
        uint_fast16_t biggestProtocolIndex = 0;
        
        for (auto protocol : eclass->protocols()) {
            writer.writeUInt16(protocol->index);
            
            if (protocol->index > biggestProtocolIndex) {
                biggestProtocolIndex = protocol->index;
            }
            if (protocol->index < smallestProtocolIndex) {
                smallestProtocolIndex = protocol->index;
            }
            
            writer.writeUInt16(protocol->methods().size());
            
            for (auto method : protocol->methods()) {
                Method *clm = eclass->getMethod(method->name);
                
                if (clm == nullptr) {
                    auto className = classType.toString(typeNothingness, true);
                    auto protocolName = Type(protocol, false).toString(typeNothingness, true);
                    ecCharToCharStack(method->name, ms);
                    compilerError(eclass->classBegin, "Class %s does not agree to protocol %s: Method %s is missing.", className.c_str(), protocolName.c_str(), ms);
                }
                
                writer.writeUInt16(clm->vti);
                clm->checkPromises(method, "protocol definition", classType);
            }
        }
        
        biggestPlaceholder.write(biggestProtocolIndex);
        smallestPlaceholder.write(smallestProtocolIndex);
    }
}
Esempio n. 17
0
Type TypeConverter::getLoweredCBridgedType(AbstractionPattern pattern,
                                           Type t,
                                           bool canBridgeBool,
                                           bool bridgedCollectionsAreOptional) {
  auto clangTy = pattern.isClangType() ? pattern.getClangType() : nullptr;

  // Bridge Bool back to ObjC bool, unless the original Clang type was _Bool
  // or the Darwin Boolean type.
  auto nativeBoolTy = getBoolType();
  if (nativeBoolTy && t->isEqual(nativeBoolTy)) {
    if (clangTy) {
      if (clangTy->isBooleanType())
        return t;
      if (clangTy->isSpecificBuiltinType(clang::BuiltinType::UChar))
        return getDarwinBooleanType();
    }
    if (clangTy || canBridgeBool)
      return getObjCBoolType();
    return t;
  }

  // Class metatypes bridge to ObjC metatypes.
  if (auto metaTy = t->getAs<MetatypeType>()) {
    if (metaTy->getInstanceType()->getClassOrBoundGenericClass()) {
      return MetatypeType::get(metaTy->getInstanceType(),
                               MetatypeRepresentation::ObjC);
    }
  }

  // ObjC-compatible existential metatypes.
  if (auto metaTy = t->getAs<ExistentialMetatypeType>()) {
    if (metaTy->getInstanceType()->isObjCExistentialType()) {
      return ExistentialMetatypeType::get(metaTy->getInstanceType(),
                                          MetatypeRepresentation::ObjC);
    }
  }
  
  // `Any` can bridge to `AnyObject` (`id` in ObjC).
  if (t->isAny()) {
    return Context.getProtocol(KnownProtocolKind::AnyObject)->getDeclaredType();
  }
  
  if (auto funTy = t->getAs<FunctionType>()) {
    switch (funTy->getExtInfo().getSILRepresentation()) {
    // Functions that are already represented as blocks or C function pointers
    // don't need bridging.
    case SILFunctionType::Representation::Block:
    case SILFunctionType::Representation::CFunctionPointer:
    case SILFunctionType::Representation::Thin:
    case SILFunctionType::Representation::Method:
    case SILFunctionType::Representation::ObjCMethod:
    case SILFunctionType::Representation::WitnessMethod:
      return t;
    case SILFunctionType::Representation::Thick: {
      // Thick functions (TODO: conditionally) get bridged to blocks.
      // This bridging is more powerful than usual block bridging, however,
      // so we use the ObjCMethod representation.
      Type newInput =
          getBridgedInputType(SILFunctionType::Representation::ObjCMethod,
                              pattern.getFunctionInputType(),
                              funTy->getInput()->getCanonicalType());
      Type newResult =
          getBridgedResultType(SILFunctionType::Representation::ObjCMethod,
                               pattern.getFunctionResultType(),
                               funTy->getResult()->getCanonicalType(),
                               /*non-optional*/false);

      return FunctionType::get(newInput, newResult,
                               funTy->getExtInfo().withSILRepresentation(
                                       SILFunctionType::Representation::Block));
    }
    }
  }

  auto foreignRepresentation =
    t->getForeignRepresentableIn(ForeignLanguage::ObjectiveC, M.TheSwiftModule);
  switch (foreignRepresentation.first) {
  case ForeignRepresentableKind::None:
  case ForeignRepresentableKind::Trivial:
  case ForeignRepresentableKind::Object:
    return t;

  case ForeignRepresentableKind::Bridged:
  case ForeignRepresentableKind::StaticBridged: {
    auto conformance = foreignRepresentation.second;
    assert(conformance && "Missing conformance?");
    Type bridgedTy =
      ProtocolConformance::getTypeWitnessByName(
        t, conformance, M.getASTContext().Id_ObjectiveCType,
        nullptr);
    assert(bridgedTy && "Missing _ObjectiveCType witness?");
    if (bridgedCollectionsAreOptional && clangTy)
      bridgedTy = OptionalType::get(bridgedTy);
    return bridgedTy;
  }

  case ForeignRepresentableKind::BridgedError: {
    auto nsErrorDecl = M.getASTContext().getNSErrorDecl();
    assert(nsErrorDecl && "Cannot bridge when NSError isn't available");
    return nsErrorDecl->getDeclaredInterfaceType();
  }
  }

  return t;
}
Esempio n. 18
0
VersionRange AvailabilityInference::inferForType(Type t) {
  AvailabilityInferenceTypeWalker walker(t->getASTContext());
  t.walk(walker);
  return walker.AvailableRange;
}
Esempio n. 19
0
bool HexagonGenExtract::convert(Instruction *In) {
  using namespace PatternMatch;
  Value *BF = 0;
  ConstantInt *CSL = 0, *CSR = 0, *CM = 0;
  BasicBlock *BB = In->getParent();
  LLVMContext &Ctx = BB->getContext();
  bool LogicalSR;

  // (and (shl (lshr x, #sr), #sl), #m)
  LogicalSR = true;
  bool Match = match(In, m_And(m_Shl(m_LShr(m_Value(BF), m_ConstantInt(CSR)),
                               m_ConstantInt(CSL)),
                         m_ConstantInt(CM)));

  if (!Match) {
    // (and (shl (ashr x, #sr), #sl), #m)
    LogicalSR = false;
    Match = match(In, m_And(m_Shl(m_AShr(m_Value(BF), m_ConstantInt(CSR)),
                            m_ConstantInt(CSL)),
                      m_ConstantInt(CM)));
  }
  if (!Match) {
    // (and (shl x, #sl), #m)
    LogicalSR = true;
    CSR = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
    Match = match(In, m_And(m_Shl(m_Value(BF), m_ConstantInt(CSL)),
                      m_ConstantInt(CM)));
    if (Match && NoSR0)
      return false;
  }
  if (!Match) {
    // (and (lshr x, #sr), #m)
    LogicalSR = true;
    CSL = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
    Match = match(In, m_And(m_LShr(m_Value(BF), m_ConstantInt(CSR)),
                            m_ConstantInt(CM)));
  }
  if (!Match) {
    // (and (ashr x, #sr), #m)
    LogicalSR = false;
    CSL = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
    Match = match(In, m_And(m_AShr(m_Value(BF), m_ConstantInt(CSR)),
                            m_ConstantInt(CM)));
  }
  if (!Match) {
    CM = 0;
    // (shl (lshr x, #sr), #sl)
    LogicalSR = true;
    Match = match(In, m_Shl(m_LShr(m_Value(BF), m_ConstantInt(CSR)),
                            m_ConstantInt(CSL)));
  }
  if (!Match) {
    CM = 0;
    // (shl (ashr x, #sr), #sl)
    LogicalSR = false;
    Match = match(In, m_Shl(m_AShr(m_Value(BF), m_ConstantInt(CSR)),
                            m_ConstantInt(CSL)));
  }
  if (!Match)
    return false;

  Type *Ty = BF->getType();
  if (!Ty->isIntegerTy())
    return false;
  unsigned BW = Ty->getPrimitiveSizeInBits();
  if (BW != 32 && BW != 64)
    return false;

  uint32_t SR = CSR->getZExtValue();
  uint32_t SL = CSL->getZExtValue();

  if (!CM) {
    // If there was no and, and the shift left did not remove all potential
    // sign bits created by the shift right, then extractu cannot reproduce
    // this value.
    if (!LogicalSR && (SR > SL))
      return false;
    APInt A = APInt(BW, ~0ULL).lshr(SR).shl(SL);
    CM = ConstantInt::get(Ctx, A);
  }

  // CM is the shifted-left mask. Shift it back right to remove the zero
  // bits on least-significant positions.
  APInt M = CM->getValue().lshr(SL);
  uint32_t T = M.countTrailingOnes();

  // During the shifts some of the bits will be lost. Calculate how many
  // of the original value will remain after shift right and then left.
  uint32_t U = BW - std::max(SL, SR);
  // The width of the extracted field is the minimum of the original bits
  // that remain after the shifts and the number of contiguous 1s in the mask.
  uint32_t W = std::min(U, T);
  if (W == 0)
    return false;

  // Check if the extracted bits are contained within the mask that it is
  // and-ed with. The extract operation will copy these bits, and so the
  // mask cannot any holes in it that would clear any of the bits of the
  // extracted field.
  if (!LogicalSR) {
    // If the shift right was arithmetic, it could have included some 1 bits.
    // It is still ok to generate extract, but only if the mask eliminates
    // those bits (i.e. M does not have any bits set beyond U).
    APInt C = APInt::getHighBitsSet(BW, BW-U);
    if (M.intersects(C) || !APIntOps::isMask(W, M))
      return false;
  } else {
    // Check if M starts with a contiguous sequence of W times 1 bits. Get
    // the low U bits of M (which eliminates the 0 bits shifted in on the
    // left), and check if the result is APInt's "mask":
    if (!APIntOps::isMask(W, M.getLoBits(U)))
      return false;
  }

  IRBuilder<> IRB(In);
  Intrinsic::ID IntId = (BW == 32) ? Intrinsic::hexagon_S2_extractu
                                   : Intrinsic::hexagon_S2_extractup;
  Module *Mod = BB->getParent()->getParent();
  Value *ExtF = Intrinsic::getDeclaration(Mod, IntId);
  Value *NewIn = IRB.CreateCall(ExtF, {BF, IRB.getInt32(W), IRB.getInt32(SR)});
  if (SL != 0)
    NewIn = IRB.CreateShl(NewIn, SL, CSL->getName());
  In->replaceAllUsesWith(NewIn);
  return true;
}
Esempio n. 20
0
// This function replaces all global variables with new variables that have
// trailing redzones. It also creates a function that poisons
// redzones and inserts this function into llvm.global_ctors.
bool AddressSanitizer::insertGlobalRedzones(Module &M) {
  SmallVector<GlobalVariable *, 16> GlobalsToChange;

  for (Module::GlobalListType::iterator G = M.getGlobalList().begin(),
       E = M.getGlobalList().end(); G != E; ++G) {
    Type *Ty = cast<PointerType>(G->getType())->getElementType();
    DEBUG(dbgs() << "GLOBAL: " << *G);

    if (!Ty->isSized()) continue;
    if (!G->hasInitializer()) continue;
    // Touch only those globals that will not be defined in other modules.
    // Don't handle ODR type linkages since other modules may be built w/o asan.
    if (G->getLinkage() != GlobalVariable::ExternalLinkage &&
        G->getLinkage() != GlobalVariable::PrivateLinkage &&
        G->getLinkage() != GlobalVariable::InternalLinkage)
      continue;
    // Two problems with thread-locals:
    //   - The address of the main thread's copy can't be computed at link-time.
    //   - Need to poison all copies, not just the main thread's one.
    if (G->isThreadLocal())
      continue;
    // For now, just ignore this Alloca if the alignment is large.
    if (G->getAlignment() > RedzoneSize) continue;

    // Ignore all the globals with the names starting with "\01L_OBJC_".
    // Many of those are put into the .cstring section. The linker compresses
    // that section by removing the spare \0s after the string terminator, so
    // our redzones get broken.
    if ((G->getName().find("\01L_OBJC_") == 0) ||
        (G->getName().find("\01l_OBJC_") == 0)) {
      DEBUG(dbgs() << "Ignoring \\01L_OBJC_* global: " << *G);
      continue;
    }

    if (G->hasSection()) {
      StringRef Section(G->getSection());
      // Ignore the globals from the __OBJC section. The ObjC runtime assumes
      // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to
      // them.
      if ((Section.find("__OBJC,") == 0) ||
          (Section.find("__DATA, __objc_") == 0)) {
        DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G);
        continue;
      }
      // See http://code.google.com/p/address-sanitizer/issues/detail?id=32
      // Constant CFString instances are compiled in the following way:
      //  -- the string buffer is emitted into
      //     __TEXT,__cstring,cstring_literals
      //  -- the constant NSConstantString structure referencing that buffer
      //     is placed into __DATA,__cfstring
      // Therefore there's no point in placing redzones into __DATA,__cfstring.
      // Moreover, it causes the linker to crash on OS X 10.7
      if (Section.find("__DATA,__cfstring") == 0) {
        DEBUG(dbgs() << "Ignoring CFString: " << *G);
        continue;
      }
    }

    GlobalsToChange.push_back(G);
  }

  size_t n = GlobalsToChange.size();
  if (n == 0) return false;

  // A global is described by a structure
  //   size_t beg;
  //   size_t size;
  //   size_t size_with_redzone;
  //   const char *name;
  // We initialize an array of such structures and pass it to a run-time call.
  StructType *GlobalStructTy = StructType::get(IntptrTy, IntptrTy,
                                               IntptrTy, IntptrTy, NULL);
  SmallVector<Constant *, 16> Initializers(n);

  IRBuilder<> IRB(CtorInsertBefore);

  for (size_t i = 0; i < n; i++) {
    GlobalVariable *G = GlobalsToChange[i];
    PointerType *PtrTy = cast<PointerType>(G->getType());
    Type *Ty = PtrTy->getElementType();
    uint64_t SizeInBytes = TD->getTypeAllocSize(Ty);
    uint64_t RightRedzoneSize = RedzoneSize +
        (RedzoneSize - (SizeInBytes % RedzoneSize));
    Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize);

    StructType *NewTy = StructType::get(Ty, RightRedZoneTy, NULL);
    Constant *NewInitializer = ConstantStruct::get(
        NewTy, G->getInitializer(),
        Constant::getNullValue(RightRedZoneTy), NULL);

    SmallString<2048> DescriptionOfGlobal = G->getName();
    DescriptionOfGlobal += " (";
    DescriptionOfGlobal += M.getModuleIdentifier();
    DescriptionOfGlobal += ")";
    GlobalVariable *Name = createPrivateGlobalForString(M, DescriptionOfGlobal);

    // Create a new global variable with enough space for a redzone.
    GlobalVariable *NewGlobal = new GlobalVariable(
        M, NewTy, G->isConstant(), G->getLinkage(),
        NewInitializer, "", G, G->isThreadLocal());
    NewGlobal->copyAttributesFrom(G);
    NewGlobal->setAlignment(RedzoneSize);

    Value *Indices2[2];
    Indices2[0] = IRB.getInt32(0);
    Indices2[1] = IRB.getInt32(0);

    G->replaceAllUsesWith(
        ConstantExpr::getGetElementPtr(NewGlobal, Indices2, true));
    NewGlobal->takeName(G);
    G->eraseFromParent();

    Initializers[i] = ConstantStruct::get(
        GlobalStructTy,
        ConstantExpr::getPointerCast(NewGlobal, IntptrTy),
        ConstantInt::get(IntptrTy, SizeInBytes),
        ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
        ConstantExpr::getPointerCast(Name, IntptrTy),
        NULL);
    DEBUG(dbgs() << "NEW GLOBAL:\n" << *NewGlobal);
  }

  ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n);
  GlobalVariable *AllGlobals = new GlobalVariable(
      M, ArrayOfGlobalStructTy, false, GlobalVariable::PrivateLinkage,
      ConstantArray::get(ArrayOfGlobalStructTy, Initializers), "");

  Function *AsanRegisterGlobals = cast<Function>(M.getOrInsertFunction(
      kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL));
  AsanRegisterGlobals->setLinkage(Function::ExternalLinkage);

  IRB.CreateCall2(AsanRegisterGlobals,
                  IRB.CreatePointerCast(AllGlobals, IntptrTy),
                  ConstantInt::get(IntptrTy, n));

  // We also need to unregister globals at the end, e.g. when a shared library
  // gets closed.
  Function *AsanDtorFunction = Function::Create(
      FunctionType::get(Type::getVoidTy(*C), false),
      GlobalValue::InternalLinkage, kAsanModuleDtorName, &M);
  BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction);
  IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB));
  Function *AsanUnregisterGlobals = cast<Function>(M.getOrInsertFunction(
      kAsanUnregisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL));
  AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage);

  IRB_Dtor.CreateCall2(AsanUnregisterGlobals,
                       IRB.CreatePointerCast(AllGlobals, IntptrTy),
                       ConstantInt::get(IntptrTy, n));
  appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndCtorPriority);

  DEBUG(dbgs() << M);
  return true;
}
Esempio n. 21
0
// FIXME: Merge with llvm::isConsecutiveAccess
bool Vectorizer::isConsecutiveAccess(Value *A, Value *B) {
  Value *PtrA = getLoadStorePointerOperand(A);
  Value *PtrB = getLoadStorePointerOperand(B);
  unsigned ASA = getPointerAddressSpace(A);
  unsigned ASB = getPointerAddressSpace(B);

  // Check that the address spaces match and that the pointers are valid.
  if (!PtrA || !PtrB || (ASA != ASB))
    return false;

  // Make sure that A and B are different pointers of the same size type.
  unsigned PtrBitWidth = DL.getPointerSizeInBits(ASA);
  Type *PtrATy = PtrA->getType()->getPointerElementType();
  Type *PtrBTy = PtrB->getType()->getPointerElementType();
  if (PtrA == PtrB ||
      PtrATy->isVectorTy() != PtrBTy->isVectorTy() ||
      DL.getTypeStoreSize(PtrATy) != DL.getTypeStoreSize(PtrBTy) ||
      DL.getTypeStoreSize(PtrATy->getScalarType()) !=
          DL.getTypeStoreSize(PtrBTy->getScalarType()))
    return false;

  APInt Size(PtrBitWidth, DL.getTypeStoreSize(PtrATy));

  unsigned IdxWidth = DL.getIndexSizeInBits(ASA);
  APInt OffsetA(IdxWidth, 0), OffsetB(IdxWidth, 0);
  PtrA = PtrA->stripAndAccumulateInBoundsConstantOffsets(DL, OffsetA);
  PtrB = PtrB->stripAndAccumulateInBoundsConstantOffsets(DL, OffsetB);

  APInt OffsetDelta = OffsetB - OffsetA;

  // Check if they are based on the same pointer. That makes the offsets
  // sufficient.
  if (PtrA == PtrB)
    return OffsetDelta == Size;

  // Compute the necessary base pointer delta to have the necessary final delta
  // equal to the size.
  APInt BaseDelta = Size - OffsetDelta;

  // Compute the distance with SCEV between the base pointers.
  const SCEV *PtrSCEVA = SE.getSCEV(PtrA);
  const SCEV *PtrSCEVB = SE.getSCEV(PtrB);
  const SCEV *C = SE.getConstant(BaseDelta);
  const SCEV *X = SE.getAddExpr(PtrSCEVA, C);
  if (X == PtrSCEVB)
    return true;

  // Sometimes even this doesn't work, because SCEV can't always see through
  // patterns that look like (gep (ext (add (shl X, C1), C2))). Try checking
  // things the hard way.

  // Look through GEPs after checking they're the same except for the last
  // index.
  GetElementPtrInst *GEPA = getSourceGEP(A);
  GetElementPtrInst *GEPB = getSourceGEP(B);
  if (!GEPA || !GEPB || GEPA->getNumOperands() != GEPB->getNumOperands())
    return false;
  unsigned FinalIndex = GEPA->getNumOperands() - 1;
  for (unsigned i = 0; i < FinalIndex; i++)
    if (GEPA->getOperand(i) != GEPB->getOperand(i))
      return false;

  Instruction *OpA = dyn_cast<Instruction>(GEPA->getOperand(FinalIndex));
  Instruction *OpB = dyn_cast<Instruction>(GEPB->getOperand(FinalIndex));
  if (!OpA || !OpB || OpA->getOpcode() != OpB->getOpcode() ||
      OpA->getType() != OpB->getType())
    return false;

  // Only look through a ZExt/SExt.
  if (!isa<SExtInst>(OpA) && !isa<ZExtInst>(OpA))
    return false;

  bool Signed = isa<SExtInst>(OpA);

  OpA = dyn_cast<Instruction>(OpA->getOperand(0));
  OpB = dyn_cast<Instruction>(OpB->getOperand(0));
  if (!OpA || !OpB || OpA->getType() != OpB->getType())
    return false;

  // Now we need to prove that adding 1 to OpA won't overflow.
  bool Safe = false;
  // First attempt: if OpB is an add with NSW/NUW, and OpB is 1 added to OpA,
  // we're okay.
  if (OpB->getOpcode() == Instruction::Add &&
      isa<ConstantInt>(OpB->getOperand(1)) &&
      cast<ConstantInt>(OpB->getOperand(1))->getSExtValue() > 0) {
    if (Signed)
      Safe = cast<BinaryOperator>(OpB)->hasNoSignedWrap();
    else
      Safe = cast<BinaryOperator>(OpB)->hasNoUnsignedWrap();
  }

  unsigned BitWidth = OpA->getType()->getScalarSizeInBits();

  // Second attempt:
  // If any bits are known to be zero other than the sign bit in OpA, we can
  // add 1 to it while guaranteeing no overflow of any sort.
  if (!Safe) {
    KnownBits Known(BitWidth);
    computeKnownBits(OpA, Known, DL, 0, nullptr, OpA, &DT);
    if (Known.countMaxTrailingOnes() < (BitWidth - 1))
      Safe = true;
  }

  if (!Safe)
    return false;

  const SCEV *OffsetSCEVA = SE.getSCEV(OpA);
  const SCEV *OffsetSCEVB = SE.getSCEV(OpB);
  const SCEV *One = SE.getConstant(APInt(BitWidth, 1));
  const SCEV *X2 = SE.getAddExpr(OffsetSCEVA, One);
  return X2 == OffsetSCEVB;
}
Esempio n. 22
0
 void Component::
 supports (Type& c, EdgeDispatcherBase& d)
 {
   iterate_and_traverse (c.supports_begin (), c.supports_end (), d);
 }
Esempio n. 23
0
Expression *TraitsExp::semantic(Scope *sc)
{
#if LOGSEMANTIC
    printf("TraitsExp::semantic() %s\n", toChars());
#endif
    if (ident != Id::compiles && ident != Id::isSame &&
        ident != Id::identifier)
    {
        TemplateInstance::semanticTiargs(loc, sc, args, 1);
    }
    size_t dim = args ? args->dim : 0;
    Declaration *d;

#define ISTYPE(cond) \
        for (size_t i = 0; i < dim; i++)        \
        {   Type *t = getType((*args)[i]);      \
            if (!t)                             \
                goto Lfalse;                    \
            if (!(cond))                        \
                goto Lfalse;                    \
        }                                       \
        if (!dim)                               \
            goto Lfalse;                        \
        goto Ltrue;

#define ISDSYMBOL(cond) \
        for (size_t i = 0; i < dim; i++)        \
        {   Dsymbol *s = getDsymbol((*args)[i]); \
            if (!s)                             \
                goto Lfalse;                    \
            if (!(cond))                        \
                goto Lfalse;                    \
        }                                       \
        if (!dim)                               \
            goto Lfalse;                        \
        goto Ltrue;



    if (ident == Id::isArithmetic)
    {
        ISTYPE(t->isintegral() || t->isfloating())
    }
    else if (ident == Id::isFloating)
    {
        ISTYPE(t->isfloating())
    }
    else if (ident == Id::isIntegral)
    {
        ISTYPE(t->isintegral())
    }
    else if (ident == Id::isScalar)
    {
        ISTYPE(t->isscalar())
    }
    else if (ident == Id::isUnsigned)
    {
        ISTYPE(t->isunsigned())
    }
    else if (ident == Id::isAssociativeArray)
    {
        ISTYPE(t->toBasetype()->ty == Taarray)
    }
    else if (ident == Id::isStaticArray)
    {
        ISTYPE(t->toBasetype()->ty == Tsarray)
    }
    else if (ident == Id::isAbstractClass)
    {
        ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
    }
    else if (ident == Id::isFinalClass)
    {
        ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
    }
    else if (ident == Id::isPOD)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (*args)[0];
        Type *t = isType(o);
        StructDeclaration *sd;
        if (!t)
        {
            error("type expected as second argument of __traits %s instead of %s", ident->toChars(), o->toChars());
            goto Lfalse;
        }
        if (t->toBasetype()->ty == Tstruct
              && ((sd = (StructDeclaration *)(((TypeStruct *)t->toBasetype())->sym)) != NULL))
        {
            if (sd->isPOD())
                goto Ltrue;
            else
                goto Lfalse;
        }
        goto Ltrue;
    }
    else if (ident == Id::isNested)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (*args)[0];
        Dsymbol *s = getDsymbol(o);
        AggregateDeclaration *a;
        FuncDeclaration *f;

        if (!s) { }
        else if ((a = s->isAggregateDeclaration()) != NULL)
        {
            if (a->isNested())
                goto Ltrue;
            else
                goto Lfalse;
        }
        else if ((f = s->isFuncDeclaration()) != NULL)
        {
            if (f->isNested())
                goto Ltrue;
            else
                goto Lfalse;
        }

        error("aggregate or function expected instead of '%s'", o->toChars());
        goto Lfalse;
    }
    else if (ident == Id::isAbstractFunction)
    {
        FuncDeclaration *f;
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
    }
Esempio n. 24
0
void LinearScan::computePreColoringHint() {
  m_preColoringHint.clear();
  IRInstruction* inst = nextNative();
  if (inst == nullptr) {
    return;
  }

  Opcode opc = inst->op();
  using NativeCalls::CallMap;
  using NativeCalls::ArgType;
  if (CallMap::hasInfo(opc)) {
    unsigned reg = 0;
    for (auto const& arg : CallMap::info(opc).args) {
      switch (arg.type) {
        case ArgType::SSA:
          m_preColoringHint.add(inst->src(arg.ival), 0, reg++);
          break;
        case ArgType::TV:
        case ArgType::MemberKeyS:
        case ArgType::MemberKeyIS:
          m_preColoringHint.add(inst->src(arg.ival), 0, reg++);
          m_preColoringHint.add(inst->src(arg.ival), 1, reg++);
          break;
        case ArgType::ExtraImm:
        case ArgType::Imm:
          break;
      }
    }
    return;
  }

  // For instructions that want to hint a continuous increasing range
  // of sources to a continuous increasing range of argument
  // registers.
  auto normalHint = [&](int count, int srcBase, int argBase) {
    for (int i = 0; i < count; ++i) {
      m_preColoringHint.add(inst->src(i + srcBase), 0,
                            i + argBase);
    }
  };
  switch (opc) {
    case LdFunc:
      m_preColoringHint.add(inst->src(0), 0, 1);
      break;
    case NativeImpl:
      m_preColoringHint.add(inst->src(1), 0, 0);
      break;
    case Concat:
      {
        Type lType = inst->src(0)->type();
        Type rType = inst->src(1)->type();
        if ((lType.isString() && rType.isString()) ||
            (lType.isString() && rType == Type::Int) ||
            (lType == Type::Int && rType.isString())) {
          m_preColoringHint.add(inst->src(0), 0, 0);
          m_preColoringHint.add(inst->src(1), 0, 1);
        } else {
          m_preColoringHint.add(inst->src(0), 0, 1);
          m_preColoringHint.add(inst->src(1), 0, 3);
        }
      }
      break;
    case AKExists:
      normalHint(2, 0, 0);
      break;
    case Eq:
    case Neq:
    case Same:
    case NSame:
      {
        auto src1 = inst->src(0);
        auto src2 = inst->src(1);

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

        if ((type1.isArray() && type2.isArray())
            || (type1.isString() && type2.isString())
            || (type1.isString() && !src1->isConst())
            || ((type1 == Type::Obj || type1 == Type::Res) &&
                (type2 == Type::Obj || type2 == Type::Res))) {
          m_preColoringHint.add(src1, 0, 0);
          m_preColoringHint.add(src2, 0, 1);
        }
      }
      break;
    case IterInit:
    case WIterInit:
      {
        m_preColoringHint.add(inst->src(0), 0, 1);
      }
      break;
    case LdSSwitchDestFast:
      normalHint(1, 0, 0);
      break;
    case LdSSwitchDestSlow:
      normalHint(1, 0, 0);
      break;
    case LdGblAddr:
      normalHint(1, 0, 0);
      break;
    case LdClsPropAddr:
      normalHint(3, 0, 0);
      break;
    case LdCls:
      m_preColoringHint.add(inst->src(0), 0, 1);
      break;
    case BoxPtr:
      normalHint(1, 0, 0);
      break;
    default:
      break;
  }
}
Esempio n. 25
0
GenericValue MCJIT::runFunction(Function *F,
                                const std::vector<GenericValue> &ArgValues) {
  assert(F && "Function *F was null at entry to run()");

  void *FPtr = getPointerToFunction(F);
  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
  FunctionType *FTy = F->getFunctionType();
  Type *RetTy = FTy->getReturnType();

  assert((FTy->getNumParams() == ArgValues.size() ||
          (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
         "Wrong number of arguments passed into function!");
  assert(FTy->getNumParams() == ArgValues.size() &&
         "This doesn't support passing arguments through varargs (yet)!");

  // Handle some common cases first.  These cases correspond to common `main'
  // prototypes.
  if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
    switch (ArgValues.size()) {
    case 3:
      if (FTy->getParamType(0)->isIntegerTy(32) &&
          FTy->getParamType(1)->isPointerTy() &&
          FTy->getParamType(2)->isPointerTy()) {
        int (*PF)(int, char **, const char **) =
          (int(*)(int, char **, const char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                 (char **)GVTOP(ArgValues[1]),
                                 (const char **)GVTOP(ArgValues[2])));
        return rv;
      }
      break;
    case 2:
      if (FTy->getParamType(0)->isIntegerTy(32) &&
          FTy->getParamType(1)->isPointerTy()) {
        int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                 (char **)GVTOP(ArgValues[1])));
        return rv;
      }
      break;
    case 1:
      if (FTy->getNumParams() == 1 &&
          FTy->getParamType(0)->isIntegerTy(32)) {
        GenericValue rv;
        int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
        return rv;
      }
      break;
    }
  }

  // Handle cases where no arguments are passed first.
  if (ArgValues.empty()) {
    GenericValue rv;
    switch (RetTy->getTypeID()) {
    default: llvm_unreachable("Unknown return type for function call!");
    case Type::IntegerTyID: {
      unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
      if (BitWidth == 1)
        rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 8)
        rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 16)
        rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 32)
        rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 64)
        rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
      else
        llvm_unreachable("Integer types > 64 bits not supported");
      return rv;
    }
    case Type::VoidTyID:
      rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
      return rv;
    case Type::FloatTyID:
      rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
      return rv;
    case Type::DoubleTyID:
      rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
      return rv;
    case Type::X86_FP80TyID:
    case Type::FP128TyID:
    case Type::PPC_FP128TyID:
      llvm_unreachable("long double not supported yet");
    case Type::PointerTyID:
      return PTOGV(((void*(*)())(intptr_t)FPtr)());
    }
  }

  llvm_unreachable("Full-featured argument passing not supported yet!");
}
Esempio n. 26
0
/*
 * Returns whether a type is generic enough to try hoisting a
 * prediction in order to specialize it.
 */
bool typeSufficientlyGeneric(Type t) {
  return t.needsReg();
}
Esempio n. 27
0
Expression *createTypeInfoArray(Scope *sc, Expression *exps[], size_t dim)
{
#if 1
    /*
     * Pass a reference to the TypeInfo_Tuple corresponding to the types of the
     * arguments. Source compatibility is maintained by computing _arguments[]
     * at the start of the called function by offseting into the TypeInfo_Tuple
     * reference.
     */
    Parameters *args = Parameters_create();
    args->setDim(dim);
    for (size_t i = 0; i < dim; i++)
    {   Parameter *arg = Parameter::create(STCin, exps[i]->type, NULL, NULL);
        (*args)[i] = arg;
    }
    TypeTuple *tup = TypeTuple::create(args);
    Expression *e = tup->getTypeInfo(sc);
    e = e->optimize(WANTvalue);
    assert(e->op == TOKsymoff);         // should be SymOffExp

    return e;
#else
    /* Improvements:
     * 1) create an array literal instead,
     * as it would eliminate the extra dereference of loading the
     * static variable.
     */

    ArrayInitializer *ai = new ArrayInitializer(0);
    VarDeclaration *v;
    Type *t;
    Expression *e;
    OutBuffer buf;
    Identifier *id;
    char *name;

    // Generate identifier for _arguments[]
    buf.writestring("_arguments_");
    for (int i = 0; i < dim; i++)
    {   t = exps[i]->type;
        t->toDecoBuffer(&buf);
    }
    buf.writeByte(0);
    id = Lexer::idPool((char *)buf.data);

    Module *m = sc->module;
    Dsymbol *s = m->symtab->lookup(id);

    if (s && s->parent == m)
    {   // Use existing one
        v = s->isVarDeclaration();
        assert(v);
    }
    else
    {   // Generate new one

        for (int i = 0; i < dim; i++)
        {   t = exps[i]->type;
            e = t->getTypeInfo(sc);
            ai->addInit(new IntegerExp(i), new ExpInitializer(Loc(), e));
        }

        t = Type::typeinfo->type->arrayOf();
        ai->type = t;
        v = new VarDeclaration(0, t, id, ai);
        v->storage_class |= STCtemp;
        m->members->push(v);
        m->symtabInsert(v);
        sc = sc->push();
        sc->linkage = LINKc;
        sc->stc = STCstatic | STCcomdat;
        ai->semantic(sc, t);
        v->semantic(sc);
        v->parent = m;
        sc = sc->pop();
    }
    e = VarExp::create(Loc(), v);
    e = e->semantic(sc);
    return e;
#endif
}
Esempio n. 28
0
void CodeGenerator::emitTypeTest(Type type, Loc typeSrc, Loc dataSrc,
                                 JmpFn doJcc) {
  assert(!type.subtypeOf(Type::Cls));

  if (type.equals(Type::Gen)) {
    return;
  }

  // You can't compare against memory. Load the type into scratch.
  m_as.     Ldrb  (rAsm.W(), typeSrc);

  ConditionCode cc;
  if (type.isString()) {
    // Note: ARM can actually do better here; it has a fused test-and-branch
    // instruction. The way this code is factored makes it difficult to use,
    // though; the jump instruction will be written by some other code.
    m_as.   Tst   (rAsm.W(), KindOfStringBit);
    cc = CC_NE;
  } else if (type.equals(Type::UncountedInit)) {
    m_as.   Tst   (rAsm.W(), KindOfUncountedInitBit);
    cc = CC_NE;
  } else if (type.equals(Type::Uncounted)) {
    m_as.   Cmp   (rAsm.W(), KindOfRefCountThreshold);
    cc = CC_LE;
  } else if (type.equals(Type::Cell)) {
    m_as.   Cmp   (rAsm.W(), KindOfRef);
    cc = CC_L;
  } else {
    assert(type.isKnownDataType());
    DataType dataType = type.toDataType();
    assert(dataType == KindOfRef ||
           (dataType >= KindOfUninit && dataType <= KindOfResource));
    m_as.   Cmp   (rAsm.W(), dataType);
    cc = CC_E;
  }
  doJcc(cc);
  if (type.strictSubtypeOf(Type::Obj) || type.strictSubtypeOf(Type::Res)) {
    assert(type.getClass()->attrs() & AttrFinal);
    m_as.   Ldr   (rAsm, dataSrc);
    m_as.   Ldr   (rAsm, rAsm[ObjectData::getVMClassOffset()]);
    m_as.   Cmp   (rAsm, reinterpret_cast<int64_t>(type.getClass()));
    doJcc(CC_E);
  } else if (type.subtypeOf(Type::Arr) && type.hasArrayKind()) {
    m_as.   Ldr   (rAsm, dataSrc);
    m_as.   Ldrb  (rAsm.W(), rAsm[ArrayData::offsetofKind()]);
    m_as.   Cmp   (rAsm.W(), type.getArrayKind());
    doJcc(CC_E);
  }
}
/// WriteTypeTable - Write out the type table for a module.
static void WriteTypeTable(const NaClValueEnumerator &VE,
                           NaClBitstreamWriter &Stream) {
  DEBUG(dbgs() << "-> WriteTypeTable\n");
  const NaClValueEnumerator::TypeList &TypeList = VE.getTypes();

  Stream.EnterSubblock(naclbitc::TYPE_BLOCK_ID_NEW, TYPE_MAX_ABBREV);

  SmallVector<uint64_t, 64> TypeVals;

  // Abbrev for TYPE_CODE_FUNCTION.
  NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev();
  Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::TYPE_CODE_FUNCTION));
  Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 1));  // isvararg
  Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array));
  Abbv->Add(NaClBitCodeAbbrevOp(TypeIdEncoding, TypeIdNumBits));
  if (TYPE_FUNCTION_ABBREV != Stream.EmitAbbrev(Abbv))
    llvm_unreachable("Unexpected abbrev ordering!");

  // Emit an entry count so the reader can reserve space.
  TypeVals.push_back(TypeList.size());
  Stream.EmitRecord(naclbitc::TYPE_CODE_NUMENTRY, TypeVals);
  TypeVals.clear();

  // Loop over all of the types, emitting each in turn.
  for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
    Type *T = TypeList[i];
    int AbbrevToUse = 0;
    unsigned Code = 0;

    switch (T->getTypeID()) {
    default: llvm_unreachable("Unknown type!");
    case Type::VoidTyID:      Code = naclbitc::TYPE_CODE_VOID;      break;
    case Type::FloatTyID:     Code = naclbitc::TYPE_CODE_FLOAT;     break;
    case Type::DoubleTyID:    Code = naclbitc::TYPE_CODE_DOUBLE;    break;
    case Type::IntegerTyID:
      // INTEGER: [width]
      Code = naclbitc::TYPE_CODE_INTEGER;
      TypeVals.push_back(cast<IntegerType>(T)->getBitWidth());
      break;
    case Type::VectorTyID: {
      VectorType *VT = cast<VectorType>(T);
      // VECTOR [numelts, eltty]
      Code = naclbitc::TYPE_CODE_VECTOR;
      TypeVals.push_back(VT->getNumElements());
      TypeVals.push_back(VE.getTypeID(VT->getElementType()));
      break;
    }
    case Type::FunctionTyID: {
      FunctionType *FT = cast<FunctionType>(T);
      // FUNCTION: [isvararg, retty, paramty x N]
      Code = naclbitc::TYPE_CODE_FUNCTION;
      TypeVals.push_back(FT->isVarArg());
      TypeVals.push_back(VE.getTypeID(FT->getReturnType()));
      for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i)
        TypeVals.push_back(VE.getTypeID(FT->getParamType(i)));
      AbbrevToUse = TYPE_FUNCTION_ABBREV;
      break;
    }
    case Type::StructTyID:
      report_fatal_error("Struct types are not supported in PNaCl bitcode");
    case Type::ArrayTyID:
      report_fatal_error("Array types are not supported in PNaCl bitcode");
    }

    // Emit the finished record.
    Stream.EmitRecord(Code, TypeVals, AbbrevToUse);
    TypeVals.clear();
  }

  Stream.ExitBlock();
  DEBUG(dbgs() << "<- WriteTypeTable\n");
}
Esempio n. 30
0
 virtual void reset(Type &row) {
   for (typename Type::iterator current = row.begin(), end = row.end();
     current != end; ++current)
   *current = typename Type::value_type();
 }