From e993ba6fca045688147321c03f0afff263a925b5 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 4 May 2009 05:16:21 +0000 Subject: [PATCH] Add -fobjc-tight-layout. - This implements gcc style Objective-C interface layout (I think). Currently it is always off, there is no functionality change unless this is passed. For the curious, the deal is that gcc lays out the fields of a subclass as if they were part of the superclass. That is, the subclass fields immediately follow the super class fields instead of being padded to the alignment of the superclass structure. - Currently gcc uses the tight layout in 32-bit and 64-bit modes, and llvm-gcc uses it in 32-bit only, for reasons which aren't clear yet. We probably want to switch to matching gcc, once this makes it through testing... my hope is that we can also fix llvm-gcc in order to maintain compatibility between the compilers. llvm-svn: 70827 --- clang/include/clang/AST/RecordLayout.h | 5 +++-- clang/include/clang/Basic/LangOptions.h | 5 ++++- clang/include/clang/Driver/Options.def | 1 + clang/lib/AST/ASTContext.cpp | 9 +++++++++ clang/lib/Driver/Tools.cpp | 1 + clang/tools/clang-cc/clang-cc.cpp | 8 ++++++++ 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/RecordLayout.h b/clang/include/clang/AST/RecordLayout.h index c68edfaf7188..57adc8a555dc 100644 --- a/clang/include/clang/AST/RecordLayout.h +++ b/clang/include/clang/AST/RecordLayout.h @@ -29,13 +29,14 @@ namespace clang { /// These objects are managed by ASTContext. class ASTRecordLayout { uint64_t Size; // Size of record in bits. + uint64_t *FieldOffsets; unsigned Alignment; // Alignment of record in bits. unsigned FieldCount; // Number of fields - uint64_t *FieldOffsets; + unsigned NextOffset; // Next available offset friend class ASTContext; ASTRecordLayout(uint64_t S = 0, unsigned A = 8) - : Size(S), Alignment(A), FieldCount(0) {} + : Size(S), Alignment(A), FieldCount(0), NextOffset(0) {} ~ASTRecordLayout() { delete [] FieldOffsets; } diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index fba474b2f527..fa5b68949054 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -37,6 +37,9 @@ public: unsigned ObjC1 : 1; // Objective-C 1 support enabled. unsigned ObjC2 : 1; // Objective-C 2 support enabled. unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled + unsigned ObjCTightLayout : 1; // Use tight interface layout, in + // which subclass ivars can be + // placed inside the superclass. unsigned PascalStrings : 1; // Allow Pascal strings unsigned WritableStrings : 1; // Allow writable strings @@ -100,7 +103,7 @@ public: Trigraphs = BCPLComment = DollarIdents = AsmPreprocessor = 0; GNUMode = ImplicitInt = Digraphs = 0; HexFloats = 0; - GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0; + GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCTightLayout = 0; C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = 0; Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0; diff --git a/clang/include/clang/Driver/Options.def b/clang/include/clang/Driver/Options.def index 13456d9531f6..5f029628e7bb 100644 --- a/clang/include/clang/Driver/Options.def +++ b/clang/include/clang/Driver/Options.def @@ -420,6 +420,7 @@ OPTION("-fobjc-gc-only", fobjc_gc_only, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fobjc-gc", fobjc_gc, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fobjc-new-property", fobjc_new_property, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) OPTION("-fobjc-nonfragile-abi", fobjc_nonfragile_abi, Flag, f_Group, INVALID, "", 0, 0, 0) +OPTION("-fobjc-tight-layout", fobjc_tight_layout, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fobjc", fobjc, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fomit-frame-pointer", fomit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fopenmp", fopenmp, Flag, f_Group, INVALID, "", 0, 0, 0) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index d89c8c2b2e3f..a9f13c951803 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -654,6 +654,9 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo, Size = FieldOffset + FieldSize; } + // Remember the next available offset. + NextOffset = Size; + // Remember max struct/class alignment. Alignment = std::max(Alignment, FieldAlign); } @@ -718,6 +721,12 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, unsigned Alignment = SL.getAlignment(); uint64_t Size = SL.getSize(); + // If we are using tight interface packing, then we start laying + // out ivars not at the end of the superclass structure, but at + // the next byte following the last field. + if (getLangOptions().ObjCTightLayout) + Size = llvm::RoundUpToAlignment(SL.NextOffset, 8); + ObjCLayouts[Key] = NewEntry = new ASTRecordLayout(Size, Alignment); NewEntry->InitializeLayout(FieldCount); // Super class is at the beginning of the layout. diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index a714be81c33a..2a959b3c55ac 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -466,6 +466,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fobjc_gc); // FIXME: Should we remove this? Args.AddLastArg(CmdArgs, options::OPT_fobjc_nonfragile_abi); + Args.AddLastArg(CmdArgs, options::OPT_fobjc_tight_layout); Args.AddLastArg(CmdArgs, options::OPT_fprint_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_ftime_report); diff --git a/clang/tools/clang-cc/clang-cc.cpp b/clang/tools/clang-cc/clang-cc.cpp index a8836887a70e..5ef2bf6c34be 100644 --- a/clang/tools/clang-cc/clang-cc.cpp +++ b/clang/tools/clang-cc/clang-cc.cpp @@ -628,6 +628,11 @@ static llvm::cl::opt ObjCNonFragileABI("fobjc-nonfragile-abi", llvm::cl::desc("enable objective-c's nonfragile abi")); + +static llvm::cl::opt +ObjCTightLayout("fobjc-tight-layout", + llvm::cl::desc("enable tight objective-c interface layout")); + static llvm::cl::opt EmitAllDecls("femit-all-decls", llvm::cl::desc("Emit all declarations, even if unused")); @@ -843,6 +848,9 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK, if (ObjCNonFragileABI) Options.ObjCNonFragileABI = 1; + + if (ObjCTightLayout) + Options.ObjCTightLayout = 1; if (EmitAllDecls) Options.EmitAllDecls = 1;