[cfe-dev] Objective-C: methods, ivars, and cleanup
Devang Patel
dpatel at apple.com
Tue Mar 25 15:03:10 PDT 2008
On Mar 25, 2008, at 10:00 AM, David Chisnall wrote:
>> + void CollectIvarTypes(ObjCInterfaceDecl *ObjCClass,
>> + std::vector<const llvm::Type*> *IvarTypes);
>>
>> This is Objective-C specific class method, so rename it as
>> CollectObjCIvarTypes.
>> Prefer SmallVector instead of std::vector. Pass it as a reference
>> instead of a pointer.
>
> Fixed passing by pointer. Kept as std::vector because
> StructType::get() takes a std::vector.
>
>> /// getLLVMFieldNo - Return llvm::StructType element number
>> /// that corresponds to the field FD.
>> unsigned getLLVMFieldNo(const FieldDecl *FD);
>> + unsigned getLLVMFieldNo(QualType ObjectTy, const ObjCIvarDecl
>> *Decl);
>>
>> Why do you need new method here ?
>
> This gets the field number from an LLVM structure created from an
> Objective-C class, rather than one created from a C structure.
> Possibly it should have a different name? Suggestions welcome.
In this method you do a field lookup by iterating over all ObjectTy
ivars. Would not it be more efficient to keep a map just like normal C
struct fields ?
>> + // Warning: Use of this is strongly discouraged. Late binding
>> of instance
>> + // variables is supported on some runtimes and so using static
>> binding can
>> + // break code when libraries are updated. Only use this if
>> you have
>> + // previously checked that the ObjCRuntime subclass in use
>> does not support
>> + // late-bound ivars.
>>
>> Please add assert() to check late-bound of ivars support.
>
> I'd like to do this, but GodeGenTypes does not have a reference to
> anything that has a reference to anything that has a reference to
> the ObjCRuntime subclass, so it's non-trivial. Suggestions welcome.
You may want to collect runtime info while constructing CodeGenTypes.
>>> runtime_if.diff contains changes to the runtime interface. This
>>> probably needs to be committed at the same time as the changes to
>>> the GNU runtime, or there might be some conflicts. The Étoilé
>>> patch may also conflict with the old definitions if it is
>>> committed before this.
>>
>> OK
>>
>> -CGObjCRuntime *CreateObjCRuntime(llvm::Module &M);
>> +CGObjCRuntime *CreateObjCRuntime(llvm::Module &M,
>> + const llvm::Type *LLVMIntType,
>> + const llvm::Type *LLVMLongType);
>>
>> Is not it possible to derive LLVMIntType and LLVMLongType info
>> based on Module ?
>
> Maybe? Can I have a hint please?
IIUC, these are target specific int and long types. In that case,
TargetInfo should provide you this info. I guess this OK for now.
> Is three slashes right for Doxygen?
yes.
>> Index: lib/CodeGen/CGStmt.cpp
>> ===================================================================
>> --- lib/CodeGen/CGStmt.cpp (revision 48734)
>> +++ lib/CodeGen/CGStmt.cpp (working copy)
>> @@ -332,9 +332,6 @@
>> // Emit the result value, even if unused, to evalute the side
>> effects.
>> const Expr *RV = S.getRetValue();
>>
>> - QualType FnRetTy = CurFuncDecl->getType().getCanonicalType();
>> - FnRetTy = cast<FunctionType>(FnRetTy)->getResultType();
>> -
>> if (FnRetTy->isVoidType()) {
>> // If the function returns void, emit ret void.
>> Builder.CreateRetVoid();
>>
>> Is this intentional ?
>
> Yes. These have been moved to instance methods variables and
> created earlier because they can not be inferred in the same way for
> Objective-C methods as for C functions.
Aha.. ok
>
>>> Finally, ivar.diff contains the code required for accessing and
>>> modifying Objective-C instance variables. This depends on the
>>> stuff in objc_struct.diff for all runtimes that do not use late-
>>> bound instance variable addresses (i.e. all of the currently
>>> supported ones).
>>
>> @@ -341,6 +345,17 @@
>> return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false));
>> else {
>> llvm::Value *V = LocalDeclMap[D];
>> + // Check if it's an implicit argument
>> + if (!V) {
>> + std::string VarName(D->getName());
>> + llvm::Function::arg_iterator AI = CurFn->arg_begin();
>> + while(AI) {
>> + if(VarName == AI->getName()) {
>> + return LValue::MakeAddr(AI);
>> + }
>> + }
>> + }
>> assert(V && "BlockVarDecl not entered in LocalDeclMap?");
>> return LValue::MakeAddr(V);
>> }
>>
>> I'm getting dense here. Please explain what is "implicit argument"
>> in this code? Thanks!
>
> In Objective-C, a method is declared like this:
>
> - (id) aMethodTakingAnInteger:(int)anInt andAnObject:(id)anObject
>
> This is then converted to a C function like this:
>
> id method(id self, SEL _cmd, int anInt, id anObject)
>
> The two first arguments are implicit - they are not specified
> explicitly in the code, but are inserted in both the caller and
> callee by the compiler. They are not always self and _cmd (they are
> in the GNU and Apple runtimes, but not in the Étoilé one).
Thanks! Make sure while(AI) is not an infinite loop.
-
Devang
More information about the cfe-dev
mailing list