[PATCH] Abstract out virtual calls and virtual function prologue code generation
Timur Iskhodzhanov
timurrrr at google.com
Tue Aug 6 09:32:56 PDT 2013
Thanks for the comments!
Please take a look at the updated patch.
2013/8/5 John McCall <rjmccall at gmail.com>:
> On Aug 2, 2013, at 2:34 AM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
>
> John,
> Any comments on this?
>
>
> +llvm::Value *ItaniumCXXABI::BuildVirtualCall(CodeGenFunction &CGF,
> + GlobalDecl GD, llvm::Value
> *This,
> + llvm::Type *Ty) {
>
> I know you’re just using an existing name here, but the function is still
> misnamed: it doesn’t actually build the call, it just gets the virtual
> function
> pointer. So, maybe getVirtualFunctionPointer?
Agreed, done.
> + llvm::Value *result =
> + CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
> "this");
> +
> + const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
> + if (MD->isVirtual()) {
> + result = CGM.getCXXABI()
> + .adjustThisParameterInVirtualFunctionPrologue(CGF, CGF.CurGD,
> result);
> + }
> +
> + getThisValue(CGF) = result;
>
> The alloca should hold the correct value; that’s important for e.g. debug
> info.
> It’d be nice to do this during argument emission, but if necessary you can
> just
> store the adjusted value back into the alloca.
Hm, I think I was able to put the correct value into alloca doing the
adjustment in CodeGenFunction::EmitFunctionProlog(), please take a
look if this approach is good enough?
// At least this produces great LLVM code now!
> + unsigned AS =
> cast<llvm::PointerType>(This->getType())->getAddressSpace();
> + llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS),
> + *thisTy = This->getType();
> + if (ML.VBase) {
> + This = CGF.Builder.CreateBitCast(This, charPtrTy);
> + const ASTRecordLayout &DerivedLayout =
> + CGF.getContext().getASTRecordLayout(MD->getParent());
> + CharUnits VBaseOffset = DerivedLayout.getVBaseClassOffset(ML.VBase);
> + This = CGF.Builder.CreateConstGEP1_64(This,
> -VBaseOffset.getQuantity());
> + }
> +
> + CharUnits StaticOffset = ML.VFTableOffset;
> + if (!StaticOffset.isZero()) {
> + assert(StaticOffset.isPositive());
> + This = CGF.Builder.CreateBitCast(This, charPtrTy);
> + This = CGF.Builder.CreateConstGEP1_64(This,
> -StaticOffset.getQuantity());
> + }
>
> Just accumulate the constant offset locally and do one gep.
Good point - done!
> You should add a quick explanation of the algorithm here, covering why using
> the vbase offset within the defining class is the right thing to do. (It
> doesn’t
> need to be too long — just a sentence or two, then just refer to the
> comments
> in the vf-table layout code for a more complete explanation.)
Done
> Also, this will eventually need vtordisp logic, right? Or is that done with
> thunks?
Yep, that's done with thunks.
> + /// VBase - If nonzero, holds the virtual base which holds this method
> + /// in its vftable.
> + const CXXRecordDecl *VBase;
>
> “nonnull” instead of “nonzero”.
>
> Also, the exact definition is that this is the virtual base subobject which
> contains
> the vf-table that the method definition is adjusted to.
Done
> + /// Stores the method's "this" implicit argument type.
> + const CXXRecordDecl *ThisType;
>
> You seem to be going through a lot of effort to propagate a type around
> that,
> frankly, isn’t even accurate when virtual bases come into play. Consider
> just
> passing it as an i8*, at least in the vbase case.
I assume you're referring to that "interesting" case when vbases got
reordered and the "this" parameter was expected to point past the
complete object?
Yeah, I was considering using i8* from the beginning, but didn't
completely come up with this special case yet...
Done, now getThisArgumentTypeForMethod() is allowed to return 0 if it
wants to indicate that we should use i8*.
I kinda agree that calculating ThisType is a somewhat redundant step
even if there is no virtual inheritance; I've put a FIXME for that
just in case.
I think my current solution (passing RD=0) is somewhat sloppy, but
can't come up with a better alternative. Do you have any suggestions
there?
[I also considered making arrangeCXXMethodType() take MD rather than
RD and making a CanQualType callback rather than RD-returning, but it
turned out arrangeCXXMethodType() should actually work with "unknown
C++ non-static member function of the given abstract type".]
> John.
More information about the cfe-commits
mailing list