Exemplo n.º 1
0
/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
/// pointer over the consumed characters.  This returns the resultant type.
static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, 
                                  Builtin::Context::GetBuiltinTypeError &Error,
                                  bool AllowTypeModifiers = true) {
  // Modifiers.
  int HowLong = 0;
  bool Signed = false, Unsigned = false;
  
  // Read the modifiers first.
  bool Done = false;
  while (!Done) {
    switch (*Str++) {
    default: Done = true; --Str; break; 
    case 'S':
      assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
      assert(!Signed && "Can't use 'S' modifier multiple times!");
      Signed = true;
      break;
    case 'U':
      assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
      assert(!Unsigned && "Can't use 'S' modifier multiple times!");
      Unsigned = true;
      break;
    case 'L':
      assert(HowLong <= 2 && "Can't have LLLL modifier");
      ++HowLong;
      break;
    }
  }

  QualType Type;
  
  // Read the base type.
  switch (*Str++) {
  default: assert(0 && "Unknown builtin type letter!");
  case 'v':
    assert(HowLong == 0 && !Signed && !Unsigned &&
           "Bad modifiers used with 'v'!");
    Type = Context.VoidTy;
    break;
  case 'f':
    assert(HowLong == 0 && !Signed && !Unsigned &&
           "Bad modifiers used with 'f'!");
    Type = Context.FloatTy;
    break;
  case 'd':
    assert(HowLong < 2 && !Signed && !Unsigned &&
           "Bad modifiers used with 'd'!");
    if (HowLong)
      Type = Context.LongDoubleTy;
    else
      Type = Context.DoubleTy;
    break;
  case 's':
    assert(HowLong == 0 && "Bad modifiers used with 's'!");
    if (Unsigned)
      Type = Context.UnsignedShortTy;
    else
      Type = Context.ShortTy;
    break;
  case 'i':
    if (HowLong == 3)
      Type = Unsigned ? Context.UnsignedInt128Ty : Context.Int128Ty;
    else if (HowLong == 2)
      Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
    else if (HowLong == 1)
      Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
    else
      Type = Unsigned ? Context.UnsignedIntTy : Context.IntTy;
    break;
  case 'c':
    assert(HowLong == 0 && "Bad modifiers used with 'c'!");
    if (Signed)
      Type = Context.SignedCharTy;
    else if (Unsigned)
      Type = Context.UnsignedCharTy;
    else
      Type = Context.CharTy;
    break;
  case 'b': // boolean
    assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
    Type = Context.BoolTy;
    break;
  case 'z':  // size_t.
    assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
    Type = Context.getSizeType();
    break;
  case 'F':
    Type = Context.getCFConstantStringType();
    break;
  case 'a':
    Type = Context.getBuiltinVaListType();
    assert(!Type.isNull() && "builtin va list type not initialized!");
    break;
  case 'A':
    // This is a "reference" to a va_list; however, what exactly
    // this means depends on how va_list is defined. There are two
    // different kinds of va_list: ones passed by value, and ones
    // passed by reference.  An example of a by-value va_list is
    // x86, where va_list is a char*. An example of by-ref va_list
    // is x86-64, where va_list is a __va_list_tag[1]. For x86,
    // we want this argument to be a char*&; for x86-64, we want
    // it to be a __va_list_tag*.
    Type = Context.getBuiltinVaListType();
    assert(!Type.isNull() && "builtin va list type not initialized!");
    if (Type->isArrayType()) {
      Type = Context.getArrayDecayedType(Type);
    } else {
      Type = Context.getLValueReferenceType(Type);
    }
    break;
  case 'V': {
    char *End;
    
    unsigned NumElements = strtoul(Str, &End, 10);
    assert(End != Str && "Missing vector size");
    
    Str = End;
    
    QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false);
    Type = Context.getVectorType(ElementType, NumElements);
    break;
  }
  case 'P': {
    IdentifierInfo *II = &Context.Idents.get("FILE");
    DeclContext::lookup_result Lookup 
      = Context.getTranslationUnitDecl()->lookup(Context, II);
    if (Lookup.first != Lookup.second && isa<TypeDecl>(*Lookup.first)) {
      Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first));
      break;
    }
    else {
      Error = Builtin::Context::GE_Missing_FILE;
      return QualType();
    }
  }
  }
  
  if (!AllowTypeModifiers)
    return Type;
  
  Done = false;
  while (!Done) {
    switch (*Str++) {
      default: Done = true; --Str; break;
      case '*':
        Type = Context.getPointerType(Type);
        break;
      case '&':
        Type = Context.getLValueReferenceType(Type);
        break;
      // FIXME: There's no way to have a built-in with an rvalue ref arg.
      case 'C':
        Type = Type.getQualifiedType(QualType::Const);
        break;
    }
  }
  
  return Type;
}
Exemplo n.º 2
0
//===----------------------------------------------------------------------===//
//                        Builtin Type Computation
//===----------------------------------------------------------------------===//
/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
/// pointer over the consumed characters.  This returns the resultant type.  If
/// AllowTypeModifiers is false then modifier like * are not parsed, just basic
/// types.  This allows "v2i*" to be parsed as a pointer to a v2i instead of
/// a vector of "i*".
///
/// RequiresICE is filled in on return to indicate whether the value is required
/// to be an Integer Constant Expression.
static Type DecodeTypeFromStr(const char *&Str,
                              const ASTContext &Context,
                              ASTContext::GetBuiltinTypeError &Error,
                              bool &RequiresICE, bool AllowTypeModifiers) {
  // Modifiers.
  int HowLong = 0;
  bool Signed = false, Unsigned = false;
  RequiresICE = false;

  // Read the prefixed modifiers first.
  bool Done = false;
  while (!Done) {
    switch (*Str++) {
    default: Done = true; --Str; break;
    case 'I':
      RequiresICE = true;
      break;
    case 'S':
      assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
      assert(!Signed && "Can't use 'S' modifier multiple times!");
      Signed = true;
      break;
    case 'U':
      assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
      assert(!Unsigned && "Can't use 'S' modifier multiple times!");
      Unsigned = true;
      break;
    case 'L':
      assert(HowLong < 4 && "Can't have LLLL modifier");
      ++HowLong;
      break;
    }
  }

  Type Ty;

  // Read the base type.
  switch (*Str++) {
  default: assert(0 && "Unknown builtin type letter!");
  case 'v':
    assert(HowLong == 0 && !Signed && !Unsigned &&
           "Bad modifiers used with 'v'!");
    // Ty = Context.VoidTy;
    break;
  case 'f':
    assert(HowLong == 0 && !Signed && !Unsigned &&
           "Bad modifiers used with 'f'!");
    Ty = Context.SingleTy;
    break;
  case 'd':
    assert(HowLong < 2 && !Signed && !Unsigned &&
           "Bad modifiers used with 'd'!");
    Ty = Context.DoubleTy;
    break;
  case 's':
    assert(HowLong == 0 && "Bad modifiers used with 's'!");
//    if (Unsigned)
//      Ty = Context.UnsignedShortTy;
//    else
//      Ty = Context.ShortTy;
    break;
  case 'i':
    if (HowLong == 3)
      Ty = Unsigned ? Context.UInt64Ty : Context.Int64Ty;
    else if (HowLong == 2)
      Ty = Unsigned ? Context.UInt32Ty : Context.Int32Ty;
    else if (HowLong == 1)
      Ty = Unsigned ? Context.UInt16Ty : Context.Int16Ty;
    else
      Ty = Unsigned ? Context.UInt8Ty : Context.Int8Ty;
    break;
  case 'c':
    assert(HowLong == 0 && "Bad modifiers used with 'c'!");
    Ty = Context.CharTy;
    break;
  case 'b': // boolean
    assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
    Ty = Context.LogicalTy;
    break;
  case 'z':  // size_t.
    assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
    // Ty = Context.getSizeType();
    break;
  case 'F':
    //Ty = Context.getCFConstantStringType();
    break;
  case 'G':
    //Ty = Context.getObjCIdType();
    break;
  case 'H':
    //Ty = Context.getObjCSelType();
    break;
  case 'a':
    //Ty = Context.getBuiltinVaListType();
    //assert(!Ty.isNull() && "builtin va list type not initialized!");
    break;
  case 'A':
    // This is a "reference" to a va_list; however, what exactly
    // this means depends on how va_list is defined. There are two
    // different kinds of va_list: ones passed by value, and ones
    // passed by reference.  An example of a by-value va_list is
    // x86, where va_list is a char*. An example of by-ref va_list
    // is x86-64, where va_list is a __va_list_tag[1]. For x86,
    // we want this argument to be a char*&; for x86-64, we want
    // it to be a __va_list_tag*.
//    Ty = Context.getBuiltinVaListType();
//    assert(!Ty.isNull() && "builtin va list type not initialized!");
//    if (Ty->isArrayType())
//      Ty = Context.getArrayDecayedType(Ty);
//    else
//      Ty = Context.getLValueReferenceType(Ty);
    break;
  case 'V': {
    char *End;
    unsigned NumElements = strtoul(Str, &End, 10);
    assert(End != Str && "Missing vector size");
    Str = End;

    Type ElementType = DecodeTypeFromStr(Str, Context, Error,
                                             RequiresICE, false);
    assert(!RequiresICE && "Can't require vector ICE");

    // TODO: No way to make AltiVec vectors in builtins yet.
    Ty = Context.getVectorType(ElementType, NumElements,
    		VectorType::GenericVector, true);
    break;
  }
  case 'X': {
    Type ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE,
                                             false);
    assert(!RequiresICE && "Can't require complex ICE");
//    Ty = Context.getComplexType(ElementType);
    break;
  }
  case 'P':
 //   Ty = Context.getFILEType();
//    if (Ty.isNull()) {
//      Error = ASTContext::GE_Missing_stdio;
      return Type();
//    }
//    break;
  case 'J':
//    if (Signed)
//      Ty = Context.getsigjmp_bufType();
//    else
//      Ty = Context.getjmp_bufType();

    if (Ty.isNull()) {
      Error = ASTContext::GE_Missing_setjmp;
      return Type();
    }
    break;
  }

  // If there are modifiers and if we're allowed to parse them, go for it.
  Done = !AllowTypeModifiers;
  while (!Done) {
    switch (/*char c =*/ *Str++) {
    default: Done = true; --Str; break;
    case '*':
    case '&': {
      // Both pointers and references can have their pointee types
      // qualified with an address space.
      char *End;
      unsigned AddrSpace = strtoul(Str, &End, 10);
      if (End != Str && AddrSpace != 0) {
//        Ty = Context.getAddrSpaceQualType(Ty, AddrSpace);
        Str = End;
      }
//      if (c == '*')
//        Ty = Context.getPointerType(Ty);
//      else
//        Ty = Context.getLValueReferenceType(Ty);
//      break;
    }
    // FIXME: There's no way to have a built-in with an rvalue ref arg.
    case 'C':
//      Ty = Ty.withConst();
      break;
    case 'D':
//      Ty = Context.getVolatileType(Ty);
      break;
    }
  }

  assert((!RequiresICE || Ty->isIntegerType()) &&
         "Integer constant 'I' type must be an integer");

  return Ty;
}