Patch to do more rewrite of __block variables.

Still WIP.

llvm-svn: 91977
This commit is contained in:
Fariborz Jahanian 2009-12-23 02:07:37 +00:00
parent 4e26c0e52b
commit 02e07737a9
1 changed files with 87 additions and 11 deletions

View File

@ -324,7 +324,7 @@ namespace {
// Block specific rewrite rules.
void RewriteBlockCall(CallExpr *Exp);
void RewriteBlockPointerDecl(NamedDecl *VD);
void RewriteByRefVar(NamedDecl *VD);
void RewriteByRefVar(VarDecl *VD);
Stmt *RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD);
void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
@ -577,6 +577,8 @@ void RewriteObjC::Initialize(ASTContext &context) {
Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
Preamble += "#define __attribute__(X)\n";
}
else
Preamble += "#define __block\n";
}
@ -3732,8 +3734,8 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
E = BlockByRefDecls.end(); I != E; ++I) {
S += " ";
std::string Name = (*I)->getNameAsString();
Context->getPointerType((*I)->getType()).getAsStringInternal(Name,
Context->PrintingPolicy);
std::string TypeString = "struct __Block_byref_" + Name + " *";
Name = TypeString + Name;
S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
}
// Next, emit a declaration for all "by copy" declarations.
@ -3859,10 +3861,10 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
S += "struct __block_impl *";
Constructor += ", void *" + ArgName;
} else {
Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName,
Context->PrintingPolicy);
Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName,
Context->PrintingPolicy);
std::string TypeString = "struct __Block_byref_" + FieldName;
TypeString += " *";
FieldName = TypeString + FieldName;
ArgName = TypeString + ArgName;
Constructor += ", " + ArgName;
}
S += FieldName + "; // by ref\n";
@ -3897,7 +3899,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
Constructor += Name + " = (struct __block_impl *)_";
else
Constructor += Name + " = _";
Constructor += Name + ";\n";
Constructor += Name + "->__forwarding;\n";
}
} else {
// Finish writing the constructor.
@ -4162,6 +4164,8 @@ void RewriteObjC::RewriteBlockCall(CallExpr *Exp) {
//}
Stmt *RewriteObjC::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
// FIXME: Add more elaborate code generation required by the ABI.
// That is, must generate BYREFVAR->__forwarding->BYREFVAR for each
// BDRE where BYREFVAR is name of the variable.
Expr *DerefExpr = new (Context) UnaryOperator(BDRE, UnaryOperator::Deref,
Context->getPointerType(BDRE->getType()),
SourceLocation());
@ -4322,7 +4326,78 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
return;
}
void RewriteObjC::RewriteByRefVar(NamedDecl *ND) {
/// RewriteByRefVar - For each __block typex ND variable this routine transforms
/// the declaration into:
/// struct __Block_byref_ND {
/// void *__isa; // NULL for everything except __weak pointers
/// struct __Block_byref_ND *__forwarding;
/// int32_t __flags;
/// int32_t __size;
/// void *__ByrefKeepFuncPtr; // Only if variable is __block ObjC object
/// void *__ByrefDestroyFuncPtr; // Only if variable is __block ObjC object
/// typex ND;
/// };
///
/// It then replaces declaration of ND variable with:
/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
/// __size=sizeof(struct __Block_byref_ND),
/// ND=initializer-if-any};
///
///
void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
const char *startBuf = SM->getCharacterData(DeclLoc);
const char *endBuf = SM->getCharacterData(ND->getLocEnd());
std::string Name(ND->getNameAsString());
std::string ByrefType = "struct __Block_byref_";
ByrefType += Name;
ByrefType += " {\n";
ByrefType += " void *__isa;\n";
ByrefType += " struct __Block_byref_" + Name + " *__forwarding;\n";
ByrefType += " int __flags;\n";
ByrefType += " int __size;\n";
// FIXME. Add void *__ByrefKeepFuncPtr; void *__ByrefDestroyFuncPtr;
// if needed.
ND->getType().getAsStringInternal(Name, Context->PrintingPolicy);
ByrefType += " " + Name + ";\n";
ByrefType += "};\n";
// Insert this type in global scope. It is needed by helper function.
assert(CurFunctionDef && "RewriteByRefVar - CurFunctionDef is null");
SourceLocation FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
InsertText(FunLocStart, ByrefType.c_str(), ByrefType.size());
// struct __Block_byref_ND ND =
// {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
// initializer-if-any};
bool hasInit = (ND->getInit() != 0);
Name = ND->getNameAsString();
ByrefType = "struct __Block_byref_" + Name;
if (!hasInit) {
ByrefType += " " + Name + " = ";
ByrefType += "{0, &" + Name + ", ";
// FIXME. Compute the flag.
ByrefType += "0, ";
ByrefType += "sizeof(struct __Block_byref_" + Name + ")";
ByrefType += "};\n";
ReplaceText(DeclLoc, endBuf-startBuf+Name.size(),
ByrefType.c_str(), ByrefType.size());
}
else {
SourceLocation startLoc = ND->getInit()->getLocStart();
ByrefType += " " + Name;
ReplaceText(DeclLoc, endBuf-startBuf,
ByrefType.c_str(), ByrefType.size());
ByrefType = " = {0, &" + Name + ", ";
// FIXME. Compute the flag.
ByrefType += "0, ";
ByrefType += "sizeof(struct __Block_byref_" + Name + "), ";
InsertText(startLoc, ByrefType.c_str(), ByrefType.size());
#if 0
ByrefType = "};\n";
SourceLocation endLoc = ND->getInit()->getLocEnd();
InsertText(startLoc, ByrefType.c_str(), ByrefType.size());
#endif
}
return;
}
@ -4671,8 +4746,9 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
RewriteBlockPointerDecl(ND);
else if (ND->getType()->isFunctionPointerType())
CheckFunctionPointerDecl(ND->getType(), ND);
if (ND->hasAttr<BlocksAttr>())
RewriteByRefVar(ND);
if (VarDecl *VD = dyn_cast<VarDecl>(SD))
if (VD->hasAttr<BlocksAttr>())
RewriteByRefVar(VD);
}
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
if (isTopLevelBlockPointerType(TD->getUnderlyingType()))