[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