void TypePrinter::Print(QualType T, std::string &S) { if (T.isNull()) { S += "NULL TYPE"; return; } if (Policy.SuppressSpecifiers && T->isSpecifierType()) return; // Print qualifiers as appropriate. Qualifiers Quals = T.getLocalQualifiers(); if (!Quals.empty()) { std::string TQS; Quals.getAsStringInternal(TQS, Policy); if (!S.empty()) { TQS += ' '; TQS += S; } std::swap(S, TQS); } switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) case Type::CLASS: \ Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \ break; #include "clang/AST/TypeNodes.def" } }
LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) { assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!"); Qualifiers Q = MakeQualifiers(E->getType()); llvm::Value *Temp = CreateMemTemp(E->getType()); EmitAggExpr(E, Temp, Q.hasVolatile()); return LValue::MakeAddr(Temp, Q); }
void ObjCMethodDecl::createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *OID) { QualType selfTy; if (isInstanceMethod()) { // There may be no interface context due to error in declaration // of the interface (which has been reported). Recover gracefully. if (OID) { selfTy = Context.getObjCInterfaceType(OID); selfTy = Context.getObjCObjectPointerType(selfTy); } else { selfTy = Context.getObjCIdType(); } } else // we have a factory method. selfTy = Context.getObjCClassType(); bool selfIsPseudoStrong = false; bool selfIsConsumed = false; if (Context.getLangOpts().ObjCAutoRefCount) { if (isInstanceMethod()) { selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); // 'self' is always __strong. It's actually pseudo-strong except // in init methods (or methods labeled ns_consumes_self), though. Qualifiers qs; qs.setObjCLifetime(Qualifiers::OCL_Strong); selfTy = Context.getQualifiedType(selfTy, qs); // In addition, 'self' is const unless this is an init method. if (getMethodFamily() != OMF_init && !selfIsConsumed) { selfTy = selfTy.withConst(); selfIsPseudoStrong = true; } } else { assert(isClassMethod()); // 'self' is always const in class methods. selfTy = selfTy.withConst(); selfIsPseudoStrong = true; } } ImplicitParamDecl *self = ImplicitParamDecl::Create(Context, this, SourceLocation(), &Context.Idents.get("self"), selfTy); setSelfDecl(self); if (selfIsConsumed) self->addAttr(new (Context) NSConsumedAttr(SourceLocation(), Context)); if (selfIsPseudoStrong) self->setARCPseudoStrong(true); setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), &Context.Idents.get("_cmd"), Context.getObjCSelType())); }
static ExprResult BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo) { // x.a is an l-value if 'a' has a reference type. Otherwise: // x.a is an l-value/x-value/pr-value if the base is (and note // that *x is always an l-value), except that if the base isn't // an ordinary object then we must have an rvalue. ExprValueKind VK = VK_LValue; ExprObjectKind OK = OK_Ordinary; if (!IsArrow) { if (BaseExpr->getObjectKind() == OK_Ordinary) VK = BaseExpr->getValueKind(); else VK = VK_RValue; } if (VK != VK_RValue && Field->isBitField()) OK = OK_BitField; // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] QualType MemberType = Field->getType(); if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) { MemberType = Ref->getPointeeType(); VK = VK_LValue; } else { QualType BaseType = BaseExpr->getType(); if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType(); Qualifiers BaseQuals = BaseType.getQualifiers(); // CVR attributes from the base are picked up by members, // except that 'mutable' members don't pick up 'const'. if (Field->isMutable()) BaseQuals.removeConst(); Qualifiers MemberQuals = S.Context.getCanonicalType(MemberType).getQualifiers(); assert(!MemberQuals.hasAddressSpace()); Qualifiers Combined = BaseQuals + MemberQuals; if (Combined != MemberQuals) MemberType = S.Context.getQualifiedType(MemberType, Combined); } S.UnusedPrivateFields.remove(Field); ExprResult Base = S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), FoundDecl, Field); if (Base.isInvalid()) return ExprError(); return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, Field, FoundDecl, MemberNameInfo, MemberType, VK, OK)); }
/// ComputeQualifierFlags - Compute the pointer type info flags from the /// given qualifier. static unsigned ComputeQualifierFlags(Qualifiers Quals) { unsigned Flags = 0; if (Quals.hasConst()) Flags |= RTTIBuilder::PTI_Const; if (Quals.hasVolatile()) Flags |= RTTIBuilder::PTI_Volatile; if (Quals.hasRestrict()) Flags |= RTTIBuilder::PTI_Restrict; return Flags; }
llvm::Value *CodeGenFunction::EmitUPCPointerDiff( llvm::Value *Pointer1, llvm::Value *Pointer2, const Expr *E) { const BinaryOperator *expr = cast<BinaryOperator>(E); Expr *LHSOperand = expr->getLHS(); QualType PtrTy = LHSOperand->getType(); llvm::Value *Phase1 = EmitUPCPointerGetPhase(Pointer1); llvm::Value *Thread1 = EmitUPCPointerGetThread(Pointer1); llvm::Value *Addr1 = EmitUPCPointerGetAddr(Pointer1); llvm::Value *Phase2 = EmitUPCPointerGetPhase(Pointer2); llvm::Value *Thread2 = EmitUPCPointerGetThread(Pointer2); llvm::Value *Addr2 = EmitUPCPointerGetAddr(Pointer2); QualType PointeeTy = PtrTy->getAs<PointerType>()->getPointeeType(); QualType ElemTy; llvm::Value *Dim; llvm::tie(ElemTy, Dim) = unwrapArray(*this, PointeeTy); Qualifiers Quals = ElemTy.getQualifiers(); llvm::Constant *ElemSize = llvm::ConstantInt::get(SizeTy, getContext().getTypeSizeInChars(ElemTy).getQuantity()); llvm::Value *AddrByteDiff = Builder.CreateSub(Addr1, Addr2, "addr.diff"); llvm::Value *AddrDiff = Builder.CreateExactSDiv(AddrByteDiff, ElemSize); llvm::Value *Result; if (Quals.getLayoutQualifier() == 0) { Result = AddrDiff; } else { llvm::Constant *B = llvm::ConstantInt::get(SizeTy, Quals.getLayoutQualifier()); llvm::Value *Threads = Builder.CreateZExt(EmitUPCThreads(), SizeTy); llvm::Value *ThreadDiff = Builder.CreateMul(Builder.CreateSub(Thread1, Thread2, "thread.diff"), B); llvm::Value *PhaseDiff = Builder.CreateSub(Phase1, Phase2, "phase.diff"); llvm::Value *BlockDiff = Builder.CreateMul(Builder.CreateSub(AddrDiff, PhaseDiff), Threads, "block.diff"); Result = Builder.CreateAdd(BlockDiff, Builder.CreateAdd(ThreadDiff, PhaseDiff), "ptr.diff"); } if (Dim) { Result = Builder.CreateExactSDiv(Result, Dim, "diff.dim"); } // FIXME: Divide by the array dimension return Result; }
static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) { QualType PointeeTy = PointerTy->getPointeeType(); const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy); if (!BuiltinTy) return false; // Check the qualifiers. Qualifiers Quals = PointeeTy.getQualifiers(); Quals.removeConst(); if (!Quals.empty()) return false; return TypeInfoIsInStandardLibrary(BuiltinTy); }
static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, const ObjCMethodDecl *Setter, const NSAPI &NS, edit::Commit &commit) { ASTContext &Context = NS.getASTContext(); std::string PropertyString = "@property"; const ParmVarDecl *argDecl = *Setter->param_begin(); QualType ArgType = Context.getCanonicalType(argDecl->getType()); Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime(); if (ArgType->isObjCRetainableType() && propertyLifetime == Qualifiers::OCL_Strong) { if (const ObjCObjectPointerType *ObjPtrTy = ArgType->getAs<ObjCObjectPointerType>()) { ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); if (IDecl && IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying"))) PropertyString += "(copy)"; } } else if (propertyLifetime == Qualifiers::OCL_Weak) // TODO. More precise determination of 'weak' attribute requires // looking into setter's implementation for backing weak ivar. PropertyString += "(weak)"; else PropertyString += "(unsafe_unretained)"; // strip off any ARC lifetime qualifier. QualType CanResultTy = Context.getCanonicalType(Getter->getResultType()); if (CanResultTy.getQualifiers().hasObjCLifetime()) { Qualifiers Qs = CanResultTy.getQualifiers(); Qs.removeObjCLifetime(); CanResultTy = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); } PropertyString += " "; PropertyString += CanResultTy.getAsString(Context.getPrintingPolicy()); PropertyString += " "; PropertyString += Getter->getNameAsString(); commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(), Getter->getDeclaratorEndLoc()), PropertyString); SourceLocation EndLoc = Setter->getDeclaratorEndLoc(); // Get location past ';' EndLoc = EndLoc.getLocWithOffset(1); commit.remove(CharSourceRange::getCharRange(Setter->getLocStart(), EndLoc)); return true; }
void MicrosoftCXXNameMangler::mangleType(QualType T) { // Only operate on the canonical type! T = getASTContext().getCanonicalType(T); Qualifiers Quals = T.getLocalQualifiers(); if (Quals) { // We have to mangle these now, while we still have enough information. // <pointer-cvr-qualifiers> ::= P # pointer // ::= Q # const pointer // ::= R # volatile pointer // ::= S # const volatile pointer if (T->isAnyPointerType() || T->isMemberPointerType() || T->isBlockPointerType()) { if (!Quals.hasVolatile()) Out << 'Q'; else { if (!Quals.hasConst()) Out << 'R'; else Out << 'S'; } } else // Just emit qualifiers like normal. // NB: When we mangle a pointer/reference type, and the pointee // type has no qualifiers, the lack of qualifier gets mangled // in there. mangleQualifiers(Quals, false); } else if (T->isAnyPointerType() || T->isMemberPointerType() || T->isBlockPointerType()) { Out << 'P'; } switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define NON_CANONICAL_TYPE(CLASS, PARENT) \ case Type::CLASS: \ llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \ return; #define TYPE(CLASS, PARENT) \ case Type::CLASS: \ mangleType(static_cast<const CLASS##Type*>(T.getTypePtr())); \ break; #include "clang/AST/TypeNodes.def" } }
/// \brief Convert the specified DeclSpec to the appropriate type object. QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) { QualType Result; switch (DS.getTypeSpecType()) { case DeclSpec::TST_integer: Result = C.IntegerTy; break; case DeclSpec::TST_unspecified: // FIXME: Correct? case DeclSpec::TST_real: Result = C.RealTy; break; case DeclSpec::TST_doubleprecision: Result = C.DoublePrecisionTy; break; case DeclSpec::TST_character: Result = C.CharacterTy; break; case DeclSpec::TST_logical: Result = C.LogicalTy; break; case DeclSpec::TST_complex: Result = C.ComplexTy; break; case DeclSpec::TST_struct: // FIXME: Finish this. break; } if (!DS.hasAttributes()) return Result; const Type *TypeNode = Result.getTypePtr(); Qualifiers Quals = Qualifiers::fromOpaqueValue(DS.getAttributeSpecs()); Quals.setIntentAttr(DS.getIntentSpec()); Quals.setAccessAttr(DS.getAccessSpec()); QualType EQs = C.getExtQualType(TypeNode, Quals, DS.getKindSelector(), DS.getLengthSelector()); if (!Quals.hasAttributeSpec(Qualifiers::AS_dimension)) return EQs; return ActOnArraySpec(C, EQs, DS.getDimensions()); }
static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, ConstantAddress DeclPtr) { assert(D.hasGlobalStorage() && "VarDecl must have global storage!"); assert(!D.getType()->isReferenceType() && "Should not call EmitDeclInit on a reference!"); QualType type = D.getType(); // Deduce UPC strict or relaxed from context, if needed if (CGF.getContext().getLangOpts().UPC) { Qualifiers Quals = type.getQualifiers(); if (Quals.hasShared() && !Quals.hasStrict() && !Quals.hasRelaxed()) { if (D.isUPCInitStrict()) Quals.addStrict(); else Quals.addRelaxed(); type = CGF.getContext().getQualifiedType(type.getUnqualifiedType(), Quals); } } LValue lv; if(type.getQualifiers().hasShared()) lv = CGF.EmitSharedVarDeclLValue(DeclPtr, type); else lv = CGF.MakeAddrLValue(DeclPtr, type); const Expr *Init = D.getInit(); switch (CGF.getEvaluationKind(type)) { case TEK_Scalar: { CodeGenModule &CGM = CGF.CGM; if (lv.isObjCStrong()) CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init), DeclPtr, D.getTLSKind()); else if (lv.isObjCWeak()) CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init), DeclPtr); else CGF.EmitScalarInit(Init, &D, lv, false); return; } case TEK_Complex: CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true); return; case TEK_Aggregate: CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased)); return; } llvm_unreachable("bad evaluation kind"); }
/// \brief Prints the part of the type string before an identifier, e.g. for /// "int foo[10]" it prints "int ". void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) { if (Policy.SuppressSpecifiers && T->isSpecifierType()) return; SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder); // Print qualifiers as appropriate. bool CanPrefixQualifiers = false; bool NeedARCStrongQualifier = false; CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier); if (CanPrefixQualifiers && !Quals.empty()) { if (NeedARCStrongQualifier) { IncludeStrongLifetimeRAII Strong(Policy); Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true); } else { Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true); } } bool hasAfterQuals = false; if (!CanPrefixQualifiers && !Quals.empty()) { hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy); if (hasAfterQuals) HasEmptyPlaceHolder = false; } switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) case Type::CLASS: \ print##CLASS##Before(cast<CLASS##Type>(T), OS); \ break; #include "clang/AST/TypeNodes.def" } if (hasAfterQuals) { if (NeedARCStrongQualifier) { IncludeStrongLifetimeRAII Strong(Policy); Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get()); } else { Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get()); } } }
void USRGenerator::VisitType(QualType T) { // This method mangles in USR information for types. It can possibly // just reuse the naming-mangling logic used by codegen, although the // requirements for USRs might not be the same. ASTContext &Ctx = *Context; do { T = Ctx.getCanonicalType(T); Qualifiers Q = T.getQualifiers(); unsigned qVal = 0; if (Q.hasConst()) qVal |= 0x1; if (Q.hasVolatile()) qVal |= 0x2; if (Q.hasRestrict()) qVal |= 0x4; if(qVal) Out << ((char) ('0' + qVal)); // Mangle in ObjC GC qualifiers? if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { Out << 'P'; T = Expansion->getPattern(); } if (const BuiltinType *BT = T->getAs<BuiltinType>()) { unsigned char c = '\0'; switch (BT->getKind()) { case BuiltinType::Void: c = 'v'; break; case BuiltinType::Bool: c = 'b'; break; case BuiltinType::Char_U: case BuiltinType::UChar: c = 'c'; break; case BuiltinType::Char16: c = 'q'; break; case BuiltinType::Char32: c = 'w'; break; case BuiltinType::UShort: c = 's'; break; case BuiltinType::UInt: c = 'i'; break; case BuiltinType::ULong: c = 'l'; break; case BuiltinType::ULongLong: c = 'k'; break; case BuiltinType::UInt128: c = 'j'; break; case BuiltinType::Char_S: case BuiltinType::SChar: c = 'C'; break; case BuiltinType::WChar_S: case BuiltinType::WChar_U: c = 'W'; break; case BuiltinType::Short: c = 'S'; break; case BuiltinType::Int: c = 'I'; break; case BuiltinType::Long: c = 'L'; break; case BuiltinType::LongLong: c = 'K'; break; case BuiltinType::Int128: c = 'J'; break; case BuiltinType::Half: c = 'h'; break; case BuiltinType::Float: c = 'f'; break; case BuiltinType::Double: c = 'd'; break; case BuiltinType::LongDouble: c = 'D'; break; case BuiltinType::NullPtr: c = 'n'; break; #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: #include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: case BuiltinType::OCLImage1d: case BuiltinType::OCLImage1dArray: case BuiltinType::OCLImage1dBuffer: case BuiltinType::OCLImage2d: case BuiltinType::OCLImage2dArray: case BuiltinType::OCLImage3d: case BuiltinType::OCLEvent: case BuiltinType::OCLSampler: IgnoreResults = true; return; case BuiltinType::ObjCId: c = 'o'; break; case BuiltinType::ObjCClass: c = 'O'; break; case BuiltinType::ObjCSel: c = 'e'; break; } Out << c; return; } // If we have already seen this (non-built-in) type, use a substitution // encoding. llvm::DenseMap<const Type *, unsigned>::iterator Substitution = TypeSubstitutions.find(T.getTypePtr()); if (Substitution != TypeSubstitutions.end()) { Out << 'S' << Substitution->second << '_'; return; } else { // Record this as a substitution. unsigned Number = TypeSubstitutions.size(); TypeSubstitutions[T.getTypePtr()] = Number; } if (const PointerType *PT = T->getAs<PointerType>()) { Out << '*'; T = PT->getPointeeType(); continue; } if (const ReferenceType *RT = T->getAs<ReferenceType>()) { Out << '&'; T = RT->getPointeeType(); continue; } if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { Out << 'F'; VisitType(FT->getResultType()); for (FunctionProtoType::arg_type_iterator I = FT->arg_type_begin(), E = FT->arg_type_end(); I!=E; ++I) { VisitType(*I); } if (FT->isVariadic()) Out << '.'; return; } if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { Out << 'B'; T = BT->getPointeeType(); continue; } if (const ComplexType *CT = T->getAs<ComplexType>()) { Out << '<'; T = CT->getElementType(); continue; } if (const TagType *TT = T->getAs<TagType>()) { Out << '$'; VisitTagDecl(TT->getDecl()); return; } if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); return; } if (const TemplateSpecializationType *Spec = T->getAs<TemplateSpecializationType>()) { Out << '>'; VisitTemplateName(Spec->getTemplateName()); Out << Spec->getNumArgs(); for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) VisitTemplateArgument(Spec->getArg(I)); return; } // Unhandled type. Out << ' '; break; } while (true); }
/// \brief Convert the specified DeclSpec to the appropriate type object. QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) { QualType Result; switch (DS.getTypeSpecType()) { case DeclSpec::TST_integer: Result = C.IntegerTy; break; case DeclSpec::TST_unspecified: // FIXME: Correct? case DeclSpec::TST_real: Result = C.RealTy; break; case DeclSpec::TST_character: if(DS.isStarLengthSelector()) Result = C.NoLengthCharacterTy; else if(DS.hasLengthSelector()) Result = QualType(C.getCharacterType( EvalAndCheckCharacterLength(DS.getLengthSelector())), 0); else Result = C.CharacterTy; break; case DeclSpec::TST_logical: Result = C.LogicalTy; break; case DeclSpec::TST_complex: Result = C.ComplexTy; break; case DeclSpec::TST_struct: if(!DS.getRecord()) Result = C.RealTy; else Result = C.getRecordType(DS.getRecord()); break; } Type::TypeKind Kind = Type::NoKind; if(DS.hasKindSelector()) Kind = EvalAndCheckTypeKind(Result, DS.getKindSelector()); if(Kind != Type::NoKind || DS.isDoublePrecision() || DS.isByte()) { switch (DS.getTypeSpecType()) { case DeclSpec::TST_integer: Result = Kind == Type::NoKind? C.IntegerTy : QualType(C.getBuiltinType(BuiltinType::Integer, Kind, true), 0); break; case DeclSpec::TST_real: Result = Kind == Type::NoKind? (DS.isDoublePrecision()? C.DoublePrecisionTy : C.RealTy) : QualType(C.getBuiltinType(BuiltinType::Real, Kind, true), 0); break; case DeclSpec::TST_logical: Result = Kind == Type::NoKind? (DS.isByte()? C.ByteTy : C.LogicalTy) : QualType(C.getBuiltinType(BuiltinType::Logical, Kind, true), 0); break; case DeclSpec::TST_complex: Result = Kind == Type::NoKind? (DS.isDoublePrecision()? C.DoubleComplexTy : C.ComplexTy) : QualType(C.getBuiltinType(BuiltinType::Complex, Kind, true), 0); break; default: break; } } if (!DS.hasAttributes()) return Result; const Type *TypeNode = Result.getTypePtr(); Qualifiers Quals = Qualifiers::fromOpaqueValue(DS.getAttributeSpecs()); Quals.setIntentAttr(DS.getIntentSpec()); Quals.setAccessAttr(DS.getAccessSpec()); Result = C.getExtQualType(TypeNode, Quals); if (!Quals.hasAttributeSpec(Qualifiers::AS_dimension)) return Result; return ActOnArraySpec(C, Result, DS.getDimensions()); }
void USRGenerator::VisitType(QualType T) { // This method mangles in USR information for types. It can possibly // just reuse the naming-mangling logic used by codegen, although the // requirements for USRs might not be the same. ASTContext &Ctx = *Context; do { T = Ctx.getCanonicalType(T); Qualifiers Q = T.getQualifiers(); unsigned qVal = 0; if (Q.hasConst()) qVal |= 0x1; if (Q.hasVolatile()) qVal |= 0x2; if (Q.hasRestrict()) qVal |= 0x4; if(qVal) Out << ((char) ('0' + qVal)); // Mangle in ObjC GC qualifiers? if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { Out << 'P'; T = Expansion->getPattern(); } if (const BuiltinType *BT = T->getAs<BuiltinType>()) { unsigned char c = '\0'; switch (BT->getKind()) { case BuiltinType::Void: c = 'v'; break; case BuiltinType::Bool: c = 'b'; break; case BuiltinType::UChar: c = 'c'; break; case BuiltinType::Char16: c = 'q'; break; case BuiltinType::Char32: c = 'w'; break; case BuiltinType::UShort: c = 's'; break; case BuiltinType::UInt: c = 'i'; break; case BuiltinType::ULong: c = 'l'; break; case BuiltinType::ULongLong: c = 'k'; break; case BuiltinType::UInt128: c = 'j'; break; case BuiltinType::Char_U: case BuiltinType::Char_S: c = 'C'; break; case BuiltinType::SChar: c = 'r'; break; case BuiltinType::WChar_S: case BuiltinType::WChar_U: c = 'W'; break; case BuiltinType::Short: c = 'S'; break; case BuiltinType::Int: c = 'I'; break; case BuiltinType::Long: c = 'L'; break; case BuiltinType::LongLong: c = 'K'; break; case BuiltinType::Int128: c = 'J'; break; case BuiltinType::Half: c = 'h'; break; case BuiltinType::Float: c = 'f'; break; case BuiltinType::Double: c = 'd'; break; case BuiltinType::LongDouble: c = 'D'; break; case BuiltinType::NullPtr: c = 'n'; break; #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: #include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/AST/OpenCLImageTypes.def" case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: case BuiltinType::OCLSampler: IgnoreResults = true; return; case BuiltinType::ObjCId: c = 'o'; break; case BuiltinType::ObjCClass: c = 'O'; break; case BuiltinType::ObjCSel: c = 'e'; break; } Out << c; return; } // If we have already seen this (non-built-in) type, use a substitution // encoding. llvm::DenseMap<const Type *, unsigned>::iterator Substitution = TypeSubstitutions.find(T.getTypePtr()); if (Substitution != TypeSubstitutions.end()) { Out << 'S' << Substitution->second << '_'; return; } else { // Record this as a substitution. unsigned Number = TypeSubstitutions.size(); TypeSubstitutions[T.getTypePtr()] = Number; } if (const PointerType *PT = T->getAs<PointerType>()) { Out << '*'; T = PT->getPointeeType(); continue; } if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) { Out << '*'; T = OPT->getPointeeType(); continue; } if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) { Out << "&&"; T = RT->getPointeeType(); continue; } if (const ReferenceType *RT = T->getAs<ReferenceType>()) { Out << '&'; T = RT->getPointeeType(); continue; } if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { Out << 'F'; VisitType(FT->getReturnType()); for (const auto &I : FT->param_types()) VisitType(I); if (FT->isVariadic()) Out << '.'; return; } if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { Out << 'B'; T = BT->getPointeeType(); continue; } if (const ComplexType *CT = T->getAs<ComplexType>()) { Out << '<'; T = CT->getElementType(); continue; } if (const TagType *TT = T->getAs<TagType>()) { Out << '$'; VisitTagDecl(TT->getDecl()); return; } if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) { Out << '$'; VisitObjCInterfaceDecl(OIT->getDecl()); return; } if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) { Out << 'Q'; VisitType(OIT->getBaseType()); for (auto *Prot : OIT->getProtocols()) VisitObjCProtocolDecl(Prot); return; } if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); return; } if (const TemplateSpecializationType *Spec = T->getAs<TemplateSpecializationType>()) { Out << '>'; VisitTemplateName(Spec->getTemplateName()); Out << Spec->getNumArgs(); for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) VisitTemplateArgument(Spec->getArg(I)); return; } if (const DependentNameType *DNT = T->getAs<DependentNameType>()) { Out << '^'; // FIXME: Encode the qualifier, don't just print it. PrintingPolicy PO(Ctx.getLangOpts()); PO.SuppressTagKeyword = true; PO.SuppressUnwrittenScope = true; PO.ConstantArraySizeAsWritten = false; PO.AnonymousTagLocations = false; DNT->getQualifier()->print(Out, PO); Out << ':' << DNT->getIdentifier()->getName(); return; } if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) { T = InjT->getInjectedSpecializationType(); continue; } // Unhandled type. Out << ' '; break; } while (true); }
void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { if (!T) { buffer += "NULL TYPE"; return; } if (Policy.SuppressSpecifiers && T->isSpecifierType()) return; // Print qualifiers as appropriate. // CanPrefixQualifiers - We prefer to print type qualifiers before the type, // so that we get "const int" instead of "int const", but we can't do this if // the type is complex. For example if the type is "int*", we *must* print // "int * const", printing "const int *" is different. Only do this when the // type expands to a simple string. bool CanPrefixQualifiers = false; bool NeedARCStrongQualifier = false; Type::TypeClass TC = T->getTypeClass(); if (const AutoType *AT = dyn_cast<AutoType>(T)) TC = AT->desugar()->getTypeClass(); if (const SubstTemplateTypeParmType *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) TC = Subst->getReplacementType()->getTypeClass(); switch (TC) { case Type::Builtin: case Type::Complex: case Type::UnresolvedUsing: case Type::Typedef: case Type::TypeOfExpr: case Type::TypeOf: case Type::Decltype: case Type::UnaryTransform: case Type::Record: case Type::Enum: case Type::Elaborated: case Type::TemplateTypeParm: case Type::SubstTemplateTypeParmPack: case Type::TemplateSpecialization: case Type::InjectedClassName: case Type::DependentName: case Type::DependentTemplateSpecialization: case Type::ObjCObject: case Type::ObjCInterface: case Type::Atomic: CanPrefixQualifiers = true; break; case Type::ObjCObjectPointer: CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() || T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType(); break; case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: NeedARCStrongQualifier = true; // Fall through case Type::Pointer: case Type::BlockPointer: case Type::LValueReference: case Type::RValueReference: case Type::MemberPointer: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: case Type::FunctionProto: case Type::FunctionNoProto: case Type::Paren: case Type::Attributed: case Type::PackExpansion: case Type::SubstTemplateTypeParm: case Type::Auto: CanPrefixQualifiers = false; break; } if (!CanPrefixQualifiers && !Quals.empty()) { std::string qualsBuffer; if (NeedARCStrongQualifier) { IncludeStrongLifetimeRAII Strong(Policy); Quals.getAsStringInternal(qualsBuffer, Policy); } else { Quals.getAsStringInternal(qualsBuffer, Policy); } if (!qualsBuffer.empty()) { if (!buffer.empty()) { qualsBuffer += ' '; qualsBuffer += buffer; } std::swap(buffer, qualsBuffer); } } switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) case Type::CLASS: \ print##CLASS(cast<CLASS##Type>(T), buffer); \ break; #include "clang/AST/TypeNodes.def" } // If we're adding the qualifiers as a prefix, do it now. if (CanPrefixQualifiers && !Quals.empty()) { std::string qualsBuffer; if (NeedARCStrongQualifier) { IncludeStrongLifetimeRAII Strong(Policy); Quals.getAsStringInternal(qualsBuffer, Policy); } else { Quals.getAsStringInternal(qualsBuffer, Policy); } if (!qualsBuffer.empty()) { if (!buffer.empty()) { qualsBuffer += ' '; qualsBuffer += buffer; } std::swap(buffer, qualsBuffer); } } }
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, bool IsMember) { // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers> // 'E' means __ptr64 (32-bit only); 'F' means __unaligned (32/64-bit only); // 'I' means __restrict (32/64-bit). // Note that the MSVC __restrict keyword isn't the same as the C99 restrict // keyword! // <base-cvr-qualifiers> ::= A # near // ::= B # near const // ::= C # near volatile // ::= D # near const volatile // ::= E # far (16-bit) // ::= F # far const (16-bit) // ::= G # far volatile (16-bit) // ::= H # far const volatile (16-bit) // ::= I # huge (16-bit) // ::= J # huge const (16-bit) // ::= K # huge volatile (16-bit) // ::= L # huge const volatile (16-bit) // ::= M <basis> # based // ::= N <basis> # based const // ::= O <basis> # based volatile // ::= P <basis> # based const volatile // ::= Q # near member // ::= R # near const member // ::= S # near volatile member // ::= T # near const volatile member // ::= U # far member (16-bit) // ::= V # far const member (16-bit) // ::= W # far volatile member (16-bit) // ::= X # far const volatile member (16-bit) // ::= Y # huge member (16-bit) // ::= Z # huge const member (16-bit) // ::= 0 # huge volatile member (16-bit) // ::= 1 # huge const volatile member (16-bit) // ::= 2 <basis> # based member // ::= 3 <basis> # based const member // ::= 4 <basis> # based volatile member // ::= 5 <basis> # based const volatile member // ::= 6 # near function (pointers only) // ::= 7 # far function (pointers only) // ::= 8 # near method (pointers only) // ::= 9 # far method (pointers only) // ::= _A <basis> # based function (pointers only) // ::= _B <basis> # based function (far?) (pointers only) // ::= _C <basis> # based method (pointers only) // ::= _D <basis> # based method (far?) (pointers only) // ::= _E # block (Clang) // <basis> ::= 0 # __based(void) // ::= 1 # __based(segment)? // ::= 2 <name> # __based(name) // ::= 3 # ? // ::= 4 # ? // ::= 5 # not really based if (!IsMember) { if (!Quals.hasVolatile()) { if (!Quals.hasConst()) Out << 'A'; else Out << 'B'; } else { if (!Quals.hasConst()) Out << 'C'; else Out << 'D'; } } else { if (!Quals.hasVolatile()) { if (!Quals.hasConst()) Out << 'Q'; else Out << 'R'; } else { if (!Quals.hasConst()) Out << 'S'; else Out << 'T'; } } // FIXME: For now, just drop all extension qualifiers on the floor. }
llvm::Value *CodeGenFunction::EmitUPCPointerArithmetic( llvm::Value *Pointer, llvm::Value *Index, QualType PtrTy, QualType IndexTy, bool IsSubtraction) { llvm::Value *Phase = EmitUPCPointerGetPhase(Pointer); llvm::Value *Thread = EmitUPCPointerGetThread(Pointer); llvm::Value *Addr = EmitUPCPointerGetAddr(Pointer); bool isSigned = IndexTy->isSignedIntegerOrEnumerationType(); unsigned width = cast<llvm::IntegerType>(Index->getType())->getBitWidth(); if (width != PointerWidthInBits) { // Zero-extend or sign-extend the pointer value according to // whether the index is signed or not. Index = Builder.CreateIntCast(Index, PtrDiffTy, isSigned, "idx.ext"); } QualType PointeeTy = PtrTy->getAs<PointerType>()->getPointeeType(); QualType ElemTy; llvm::Value *Dim; llvm::tie(ElemTy, Dim) = unwrapArray(*this, PointeeTy); if (Dim) { Index = Builder.CreateMul(Index, Dim, "idx.dim", !isSigned, isSigned); } Qualifiers Quals = ElemTy.getQualifiers(); if (IsSubtraction) Index = Builder.CreateNeg(Index); if (Quals.getLayoutQualifier() == 0) { // UPC 1.2 6.4.2p2 // If the shared array is declared with indefinite block size, // the result of the pointer-to-shared arithmetic is identical // to that described for normal C pointers in [IOS/IEC00 Sec 6.5.2] // except that the thread of the new pointer shall be the // same as that of the original pointer and the phase // component is defined to always be zero. uint64_t ElemSize = getContext().getTypeSizeInChars(ElemTy).getQuantity(); llvm::Value *ByteIndex = Builder.CreateMul(Index, llvm::ConstantInt::get(SizeTy, ElemSize)); Addr = Builder.CreateAdd(Addr, ByteIndex, "add.addr"); } else { llvm::Value *OldPhase = Phase; llvm::Constant *B = llvm::ConstantInt::get(SizeTy, Quals.getLayoutQualifier()); llvm::Value *Threads = Builder.CreateZExt(EmitUPCThreads(), SizeTy); llvm::Value *GlobalBlockSize = Builder.CreateNUWMul(Threads, B); // Combine the Phase and Thread into a single unit llvm::Value *TmpPhaseThread = Builder.CreateNUWAdd(Builder.CreateNUWMul(Thread, B), Phase); TmpPhaseThread = Builder.CreateAdd(TmpPhaseThread, Index); // Div is the number of (B * THREADS) blocks that we need to jump // Rem is Thread * B + Phase llvm::Value *Div = Builder.CreateSDiv(TmpPhaseThread, GlobalBlockSize); llvm::Value *Rem = Builder.CreateSRem(TmpPhaseThread, GlobalBlockSize); // Fix the result of the division/modulus llvm::Value *Test = Builder.CreateICmpSLT(Rem, llvm::ConstantInt::get(SizeTy, 0)); Rem = Builder.CreateSelect(Test, Builder.CreateAdd(Rem, GlobalBlockSize), Rem); llvm::Value *DecDiv = Builder.CreateSub(Div, llvm::ConstantInt::get(SizeTy, 1)); Div = Builder.CreateSelect(Test, DecDiv, Div); // Split out the Phase and Thread components Thread = Builder.CreateUDiv(Rem, B); Phase = Builder.CreateURem(Rem, B); uint64_t ElemSize = getContext().getTypeSizeInChars(ElemTy).getQuantity(); // Compute the final Addr. llvm::Value *AddrInc = Builder.CreateMul(Builder.CreateAdd(Builder.CreateSub(Phase, OldPhase), Builder.CreateMul(Div, B)), llvm::ConstantInt::get(SizeTy, ElemSize)); Addr = Builder.CreateAdd(Addr, AddrInc); } return EmitUPCPointer(Phase, Thread, Addr); }
llvm::Value *CodeGenFunction::EmitUPCPointerCompare( llvm::Value *Pointer1, llvm::Value *Pointer2, const BinaryOperator *E) { QualType PtrTy = E->getLHS()->getType(); QualType PointeeTy = PtrTy->getAs<PointerType>()->getPointeeType(); QualType ElemTy = PointeeTy; while (const ArrayType *AT = getContext().getAsArrayType(ElemTy)) ElemTy = AT->getElementType(); Qualifiers Quals = ElemTy.getQualifiers(); // Use the standard transformations so we only // have to implement < and ==. bool Flip = false; switch (E->getOpcode()) { case BO_EQ: break; case BO_NE: Flip = true; break; case BO_LT: break; case BO_GT: std::swap(Pointer1, Pointer2); break; case BO_LE: std::swap(Pointer1, Pointer2); Flip = true; break; case BO_GE: Flip = true; break; default: llvm_unreachable("expected a comparison operator"); } llvm::Value *Phase1 = EmitUPCPointerGetPhase(Pointer1); llvm::Value *Thread1 = EmitUPCPointerGetThread(Pointer1); llvm::Value *Addr1 = EmitUPCPointerGetAddr(Pointer1); llvm::Value *Phase2 = EmitUPCPointerGetPhase(Pointer2); llvm::Value *Thread2 = EmitUPCPointerGetThread(Pointer2); llvm::Value *Addr2 = EmitUPCPointerGetAddr(Pointer2); llvm::Value *Result; // Equality has to work correctly even if the pointers // are not in the same array. if (E->getOpcode() == BO_EQ || E->getOpcode() == BO_NE) { Result = Builder.CreateAnd(Builder.CreateICmpEQ(Addr1, Addr2), Builder.CreateICmpEQ(Thread1, Thread2)); } else if (Quals.getLayoutQualifier() == 0) { Result = Builder.CreateICmpULT(Addr1, Addr2); } else { llvm::IntegerType *BoolTy = llvm::Type::getInt1Ty(CGM.getLLVMContext()); llvm::Constant *LTResult = llvm::ConstantInt::get(BoolTy, 1); llvm::Constant *GTResult = llvm::ConstantInt::get(BoolTy, 0); llvm::Constant *ElemSize = llvm::ConstantInt::get(SizeTy, getContext().getTypeSizeInChars(ElemTy).getQuantity()); llvm::Value *AddrByteDiff = Builder.CreateSub(Addr1, Addr2, "addr.diff"); llvm::Value *PhaseDiff = Builder.CreateSub(Phase1, Phase2, "phase.diff"); llvm::Value *PhaseByteDiff = Builder.CreateMul(PhaseDiff, ElemSize); llvm::Value *TestBlockLT = Builder.CreateICmpSLT(AddrByteDiff, PhaseByteDiff); llvm::Value *TestBlockEQ = Builder.CreateICmpEQ(AddrByteDiff, PhaseByteDiff); llvm::Value *TestThreadLT = Builder.CreateICmpULT(Thread1, Thread2); llvm::Value *TestThreadEQ = Builder.CreateICmpEQ(Thread1, Thread2); // Compare the block first, then the thread, then the phase Result = Builder.CreateSelect(TestBlockLT, LTResult, Builder.CreateSelect(TestBlockEQ, Builder.CreateSelect(TestThreadLT, LTResult, Builder.CreateSelect(TestThreadEQ, Builder.CreateICmpULT(Phase1, Phase2), GTResult)), GTResult)); } if (Flip) Result = Builder.CreateNot(Result); return Result; }
void VisitQualifiers(Qualifiers Quals) { ID.AddInteger(Quals.getAsOpaqueValue()); }