From: Douglas Gregor Date: Tue, 1 Feb 2011 15:15:22 +0000 (+0000) Subject: Basic support for -mms-bitfields, from Carl Norum! X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f75550e40a9177db9979fc130ce3ece026b137d;p=clang Basic support for -mms-bitfields, from Carl Norum! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124661 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 263a6b1e3d..819f5f0867 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -85,7 +85,8 @@ def err_verify_missing_end : Error< def err_verify_invalid_content : Error< "invalid expected %0: %1">; def err_verify_inconsistent_diags : Error< - "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: %2">; + "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: " + "%2">; def note_fixit_applied : Note<"FIX-IT applied suggested code changes">; def note_fixit_in_macro : Note< @@ -150,6 +151,9 @@ def warn_pch_gnu_keywords : Error< def warn_pch_microsoft_extensions : Error< "Microsoft extensions were %select{disabled|enabled}0 in PCH file but are " "currently %select{disabled|enabled}1">; +def warn_pch_ms_bitfields : Error< + "Microsoft-compatible structure layout was %select{disabled|enabled}0 in " + "PCH file but is currently %select{disabled|enabled}1">; def warn_pch_heinous_extensions : Error< "heinous extensions were %select{disabled|enabled}0 in PCH file but are " "currently %select{disabled|enabled}1">; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index f31c4ff6fb..74ae70b52e 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -56,6 +56,7 @@ public: unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling. unsigned RTTI : 1; // Support RTTI information. + unsigned MSBitfields : 1; // MS-compatible structure layout unsigned NeXTRuntime : 1; // Use NeXT runtime. unsigned Freestanding : 1; // Freestanding implementation unsigned NoBuiltin : 1; // Do not use builtin functions (-fno-builtin) @@ -163,6 +164,7 @@ public: C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0; + MSBitfields = 0; NeXTRuntime = 1; RTTI = 1; LaxVectorConversions = 1; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 12800a8e80..fd9bec0661 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -183,6 +183,8 @@ def munwind_tables : Flag<"-munwind-tables">, HelpText<"Generate unwinding tables for all functions">; def mconstructor_aliases : Flag<"-mconstructor-aliases">, HelpText<"Emit complete constructors and destructors as aliases when possible">; +def mms_bitfields : Flag<"-mms-bitfields">, + HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">; def O : Joined<"-O">, HelpText<"Optimization level">; def Os : Flag<"-Os">, HelpText<"Optimize for size">; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 02f41846d4..735bb2d6f3 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -476,6 +476,7 @@ def mkernel : Flag<"-mkernel">, Group; def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>; def mllvm : Separate<"-mllvm">; def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group; +def mms_bitfields : Flag<"-mms-bitfields">, Group; def mmmx : Flag<"-mmmx">, Group; def mno_3dnowa : Flag<"-mno-3dnowa">, Group; def mno_3dnow : Flag<"-mno-3dnow">, Group; diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 7e15dcce37..730ec21358 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1402,6 +1402,20 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { std::pair FieldInfo = Context.getTypeInfo(D->getType()); FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; + + if (Context.getLangOptions().MSBitfields) { + // If MS bitfield layout is required, figure out what type is being + // laid out and align the field to the width of that type. + + // Resolve all typedefs down to their base type and round up the field + // alignment if necessary. + QualType T = Context.getBaseElementType(D->getType()); + if (const BuiltinType *BTy = T->getAs()) { + uint64_t TypeSize = Context.getTypeSize(BTy); + if (TypeSize > FieldAlign) + FieldAlign = TypeSize; + } + } } // The align if the field is not packed. This is to check if the attribute diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index d11db7ed2d..8f8c64d460 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1028,6 +1028,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // work around a linker bug; see . if (getToolChain().getTriple().getOS() != llvm::Triple::Darwin) CmdArgs.push_back("-mconstructor-aliases"); + + if (Args.hasArg(options::OPT_mms_bitfields)) { + CmdArgs.push_back("-mms-bitfields"); + } // This is a coarse approximation of what llvm-gcc actually does, both // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3fdbc1683c..9ad41458b8 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -583,6 +583,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fsjlj-exceptions"); if (!Opts.RTTI) Res.push_back("-fno-rtti"); + if (Opts.MSBitfields) + Res.push_back("-mms-bitfields"); if (!Opts.NeXTRuntime) Res.push_back("-fgnu-runtime"); if (Opts.Freestanding) @@ -1445,6 +1447,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Diags); Opts.NumLargeByValueCopy = Args.getLastArgIntValue(OPT_Wlarge_by_value_copy, 0, Diags); + Opts.MSBitfields = Args.hasArg(OPT_mms_bitfields); Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); Opts.ObjCConstantStringClass = Args.getLastArgValue(OPT_fconstant_string_class); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 7e7bd253af..1e07e76314 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -96,6 +96,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec); PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions); PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions); + PARSE_LANGOPT_IMPORTANT(MSBitfields, diag::warn_pch_ms_bitfields); PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime); PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding); PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins); @@ -2613,6 +2614,7 @@ bool ASTReader::ParseLanguageOptions( PARSE_LANGOPT(AltiVec); PARSE_LANGOPT(Exceptions); PARSE_LANGOPT(SjLjExceptions); + PARSE_LANGOPT(MSBitfields); PARSE_LANGOPT(NeXTRuntime); PARSE_LANGOPT(Freestanding); PARSE_LANGOPT(NoBuiltin); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index e90640711f..b85aac1cc9 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -911,6 +911,7 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.Exceptions); // Support exception handling. Record.push_back(LangOpts.SjLjExceptions); + Record.push_back(LangOpts.MSBitfields); // MS-compatible structure layout Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime. Record.push_back(LangOpts.Freestanding); // Freestanding implementation Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin) diff --git a/test/CodeGen/mms-bitfields.c b/test/CodeGen/mms-bitfields.c new file mode 100644 index 0000000000..1617e8ac40 --- /dev/null +++ b/test/CodeGen/mms-bitfields.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -mms-bitfields -emit-llvm %s -o - | FileCheck %s + +struct s1 { + int f32; + long long f64; +} s1; + +// CHECK: %struct.s1 = type { i32, [4 x i8], i64 } + +struct s2 { + int f32; + long long f64[4]; +} s2; + +// CHECK: %struct.s2 = type { i32, [4 x i8], [4 x i64] } + +struct s3 { + int f32; + struct s1 s; +} s3; + +// CHECK: %struct.s3 = type { i32, [4 x i8], %struct.s1 }