Add (partial) support for @encode.

llvm-svn: 43439
This commit is contained in:
Anders Carlsson 2007-10-29 05:01:08 +00:00
parent 3692dbe492
commit d849982e84
4 changed files with 126 additions and 1 deletions

View File

@ -16,6 +16,8 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
enum FloatingRank {
@ -835,6 +837,104 @@ QualType ASTContext::getCFConstantStringType() {
return getTagDeclType(CFConstantStringTypeDecl);
}
static bool isTypeTypedefedAsBOOL(QualType T)
{
if (const PointerType *NCPT = T->getAsPointerType())
if (const TypedefType *TT = dyn_cast<TypedefType>(NCPT->getPointeeType()))
if (!strcmp(TT->getDecl()->getName(), "BOOL"))
return true;
return false;
}
void ASTContext::getObjcEncodingForType(QualType T, std::string& S) const
{
QualType Ty = T.getCanonicalType();
if (const BuiltinType *BT = Ty->getAsBuiltinType()) {
char encoding;
switch (BT->getKind()) {
case BuiltinType::Void:
encoding = 'v';
break;
case BuiltinType::Bool:
encoding = 'B';
break;
case BuiltinType::Char_U:
case BuiltinType::UChar:
encoding = 'C';
break;
case BuiltinType::UShort:
encoding = 'S';
break;
case BuiltinType::UInt:
encoding = 'I';
break;
case BuiltinType::ULong:
encoding = 'L';
break;
case BuiltinType::ULongLong:
encoding = 'Q';
break;
case BuiltinType::Char_S:
case BuiltinType::SChar:
encoding = 'c';
break;
case BuiltinType::Short:
encoding = 's';
break;
case BuiltinType::Int:
encoding = 'i';
break;
case BuiltinType::Long:
encoding = 'l';
break;
case BuiltinType::LongLong:
encoding = 'q';
break;
case BuiltinType::Float:
encoding = 'f';
break;
case BuiltinType::Double:
encoding = 'd';
break;
case BuiltinType::LongDouble:
encoding = 'd';
break;
default:
assert(0 && "Unhandled builtin type kind");
}
S += encoding;
} else if (const PointerType *PT = Ty->getAsPointerType()) {
QualType PointeeTy = PT->getPointeeType();
if (PointeeTy->isCharType()) {
// char pointer types should be encoded as '*' unless it is a
// type that has been typedef'd to 'BOOL'.
if (isTypeTypedefedAsBOOL(T)) {
S += '*';
return;
}
}
S += '^';
getObjcEncodingForType(PT->getPointeeType(), S);
} else if (const ArrayType *AT = Ty->getAsArrayType()) {
S += '[';
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
S += llvm::utostr(CAT->getSize().getZExtValue());
else
assert(0 && "Unhandled array type!");
getObjcEncodingForType(AT->getElementType(), S);
S += ']';
} else
fprintf(stderr, "@encode for type %s not implemented!\n",
Ty.getAsString().c_str());
}
void ASTContext::setBuiltinVaListType(QualType T)
{
assert(BuiltinVaListType.isNull() && "__builtin_va_list type already set!");

View File

@ -16,6 +16,7 @@
#include "clang/AST/AST.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
@ -262,6 +263,7 @@ public:
Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
return CGF.EmitObjCStringLiteral(E);
}
Value *VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
};
} // end anonymous namespace.
@ -917,6 +919,23 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE)
return V;
}
Value *ScalarExprEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E)
{
std::string str;
CGF.getContext().getObjcEncodingForType(E->getEncodedType(), str);
llvm::Constant *C = llvm::ConstantArray::get(str);
C = new llvm::GlobalVariable(C->getType(), true,
llvm::GlobalValue::InternalLinkage,
C, ".str", &CGF.CGM.getModule());
llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero };
C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
return C;
}
//===----------------------------------------------------------------------===//
// Entry Point into this File
//===----------------------------------------------------------------------===//

View File

@ -329,7 +329,10 @@ Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
// Create a new string expression.
QualType StrType = Context->getPointerType(Context->CharTy);
Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
std::string StrEncoding;
Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
StrEncoding.length(), false, StrType,
SourceLocation(), SourceLocation());
Rewrite.ReplaceStmt(Exp, Replacement);
delete Exp;

View File

@ -171,6 +171,9 @@ public:
return ObjcConstantStringType;
}
// Return the ObjC type encoding for a given type.
void getObjcEncodingForType(QualType t, std::string &S) const;
// This setter/getter repreents the ObjC 'id' type. It is setup lazily, by
// Sema.
void setObjcIdType(TypedefDecl *Decl);