diff options
-rw-r--r-- | docs/LangRef.html | 137 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 65 | ||||
-rw-r--r-- | lib/Target/X86/X86FrameLowering.cpp | 19 |
3 files changed, 208 insertions, 13 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html index 2799083748..6881620cbc 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -106,6 +106,11 @@ <li><a href="#fpaccuracy">'<tt>fpaccuracy</tt>' Metadata</a></li> </ol> </li> + <li><a href="#module_flags">Module Flags Metadata</a> + <ol> + <li><a href="#objc_metadata">Objective-C Metadata</a></li> + </ol> + </li> </ol> </li> <li><a href="#intrinsic_globals">Intrinsic Global Variables</a> @@ -3026,6 +3031,138 @@ call void @llvm.dbg.value(metadata !24, i64 0, metadata !25) </div> +<!-- ======================================================================= --> +<h3> + <a name="module_flags">Module Flags Metadata</a> +</h3> + +<div> + +<p>Occasionally, the front-end needs to transmit data to the linker which + affects its behavior. The LLVM IR isn't sufficient to transmit this + information, so one should use the <tt>llvm.module.flags</tt> named + metadata.</p> + +<p>The <tt>llvm.module.flags</tt> metadata is a named metadata, whose elements + consist of metadata triplets. For example:</p> + +<pre class="doc_code"> +!0 = metadata !{ i32 0, metadata !"foo", i32 1 } +!1 = metadata !{ i32 1, metadata !"bar", i32 37 } + +!llvm.module.flags = !{ !0, !1 } +</pre> + +<p>The first field specifies the behavior of the linker upon encountering two of + the same values. Behavior could range from: emitting an error if some of the + modules' flags disagree, emitting a warning, etc. The second field is the + name of the metadata. The third field is the value of the metadata.</p> + +<p>When two modules are linked together, the <tt>llvm.module.flags</tt> metadata + are unioned together.</p> + +</div> + +<!-- _______________________________________________________________________ --> +<h4> + <a name="objc_metadata">Objective-C Metadata</a> +</h4> + +<div> + +<p>The following module flags are used to convey Objective-C metadata to the + linker.</p> + +<table border="1" cellspacing="0" cellpadding="4"> + <tbody> + <tr> + <th>Value</th> + <th>Behavior</th> + </tr> + <tr> + <td>1</td> + <td align="left"> + <dl> + <dt><tt>Error</tt></dt> + <dd>Causes the linker to emit an error when two values disagree.</dd> + </dl> + </td> + </tr> + <tr> + <td>2</td> + <td align="left"> + <dl> + <dt><tt>Require</tt></dt> + <dd>Causes the linker to emit an error when the specified value is not + present.</dd> + </dl> + </td> + </tr> + <tr> + <td>3</td> + <td align="left"> + <dl> + <dt><tt>Override</tt></dt> + <dd>Causes the linker to use the specified value if the two values + disagree. It's an error if two pieces of the same metadata have + the <tt>Override</tt> behavior but different values.</dd> + </dl> + </td> + </tr> + </tbody> +</table> + +<p>The names are:</p> + +<ul> + <li><tt>Objective-C Version</tt></li> + <li><tt>Objective-C Garbage Collection</tt></li> + <li><tt>Objective-C GC Only</tt></li> + <li><tt>Objective-C Image Info Section</tt></li> +</ul> + +<p> + +<p>Here is an example of how to use the Objective-C metadata:</p> + +<pre class="doc_code"> +<u>Module A</u> +!0 = metadata !{ i32 1, metadata !"Objective-C Version", i32 2 } +!1 = metadata !{ i32 1, metadata !"Objective-C Garbage Collection", i32 2 } +!2 = metadata !{ i32 1, metadata !"Objective-C Image Info Section", + metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip" } +!llvm.module.flags = !{ !0, !1, !2 } + +<u>Module B</u> +!0 = metadata !{ i32 1, metadata !"Objective-C Version", i32 2 } +!1 = metadata !{ i32 1, metadata !"Objective-C Garbage Collection", i32 2 } +!2 = metadata !{ i32 1, metadata !"Objective-C GC Only", i32 4 } +!3 = metadata !{ i32 1, metadata !"Objective-C Image Info Section", + metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip" } +!4 = metadata !{ i32 2, metadata !"Objective-C GC Only", + metadata !{ + metadata !"Objective-C Garbage Collection", i32 2 + } +} +!llvm.module.flags = !{ !0, !1, !2, !3, !4 } + +<u>Linked Module</u> +!0 = metadata !{ i32 1, metadata !"Objective-C Version", i32 2 } +!1 = metadata !{ i32 3, metadata !"Objective-C Garbage Collection", i32 2 } +!2 = metadata !{ i32 1, metadata !"Objective-C GC Only", i32 4 } +!3 = metadata !{ i32 1, metadata !"Objective-C Image Info Section", + metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip" } +!4 = metadata !{ i32 2, metadata !"Objective-C GC Only", + metadata !{ + metadata !"Objective-C Garbage Collection", i32 2 + } +} +!llvm.module.flags = !{ !0, !1, !2, !3, !4 } +</pre> + + +</div> + </div> <!-- *********************************************************************** --> diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 82860c2657..1b15cdcc81 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -930,6 +930,71 @@ bool AsmPrinter::doFinalization(Module &M) { if (const MCSection *S = MAI->getNonexecutableStackSection(OutContext)) OutStreamer.SwitchSection(S); + // If we have module flags, then emit them. + NamedMDNode *ModFlags = M.getNamedMetadata("llvm.module.flags"); + if (ModFlags) { + const char *ObjCGCName = "Objective-C Garbage Collection"; + const char *ObjCGCOnlyName = "Objective-C GC Only"; + const char *ObjCImageInfoVersion = "Objective-C Image Info Version"; + const char *ObjCImageInfoSec = "Objective-C Image Info Section"; + + MDNode *GC = 0; + MDNode *GCOnly = 0; + MDNode *ImageInfoVersion = 0; + MDNode *ImageInfoSec = 0; + + for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) { + MDNode *MD = ModFlags->getOperand(I); + unsigned Behavior = cast<ConstantInt>(MD->getOperand(0))->getZExtValue(); + (void) Behavior; + MDString *Str = cast<MDString>(MD->getOperand(1)); + + if (Str->getString() == ObjCImageInfoVersion) { + assert(Behavior == 1 && "Invalid behavior for module flag!"); + ImageInfoVersion = MD; + } else if (Str->getString() == ObjCGCName) { + assert((Behavior == 1 || Behavior == 3) && + "Invalid behavior for module flag!"); + GC = MD; + } else if (Str->getString() == ObjCGCOnlyName) { + if (Behavior == 2) continue; // Ignore the 'require' clause. + GCOnly = MD; + } else if (Str->getString() == ObjCImageInfoSec) { + assert(Behavior == 1 && "Invalid behavior for module flag!"); + ImageInfoSec = MD; + } + } + + if (ImageInfoVersion || GC || GCOnly || ImageInfoSec) { + // FIXME: Duh! + unsigned version = 0; + unsigned flags = 0; + + version = + cast<ConstantInt>(ImageInfoVersion->getOperand(2))->getZExtValue(); + if (GC) + flags |= cast<ConstantInt>(GC->getOperand(2))->getZExtValue(); + if (GCOnly) + flags |= cast<ConstantInt>(GCOnly->getOperand(2))->getZExtValue(); + + Type *Int32Ty = Type::getInt32Ty(M.getContext()); + Constant *values[2] = { + ConstantInt::get(Int32Ty, version), + ConstantInt::get(Int32Ty, flags) + }; + ArrayType *AT = ArrayType::get(Int32Ty, 2); + StringRef Sec = cast<MDString>(ImageInfoSec->getOperand(2))->getString(); + + GlobalVariable *GV = + cast<GlobalVariable>(M.getOrInsertGlobal("L_OBJC_IMAGE_INFO", AT)); + GV->setConstant(true); + GV->setSection(Sec); + GV->setInitializer(ConstantArray::get(AT, values)); + + EmitGlobalVariable(GV); + } + } + // Allow the target to emit any magic that it wants at the end of the file, // after everything else has gone out. EmitEndOfAsmFile(M); diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index e5f6752614..5dfc0bb85d 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -455,26 +455,19 @@ encodeCompactUnwindRegistersWithFrame(unsigned SavedRegs[CU_NUM_SAVED_REGS], }; const unsigned *CURegs = (Is64Bit ? CU64BitRegs : CU32BitRegs); - // FIXME: The code below is WRONG and breaks tests on i386, see - // SingleSource/Regression/C++/EH/ctor_dtor_count.exec - // SingleSource/Regression/C++/EH/exception_spec_test.exec - // SingleSource/Regression/C++/EH/function_try_block.exec - // SingleSource/Regression/C++/EH/throw_rethrow_test.exec - return ~0U; - // Encode the registers in the order they were saved, 3-bits per register. The - // registers are numbered from 1 to 6. + // registers are numbered from 1 to CU_NUM_SAVED_REGS. uint32_t RegEnc = 0; - for (int I = 0; I != 6; ++I) { + for (int I = CU_NUM_SAVED_REGS, Idx = 0; I != -1; --I) { unsigned Reg = SavedRegs[I]; - if (Reg == 0) break; + if (Reg == 0) continue; + int CURegNum = getCompactUnwindRegNum(CURegs, Reg); - if (CURegNum == -1) - return ~0U; + if (CURegNum == -1) return ~0U; // Encode the 3-bit register number in order, skipping over 3-bits for each // register. - RegEnc |= (CURegNum & 0x7) << ((5 - I) * 3); + RegEnc |= (CURegNum & 0x7) << (Idx++ * 3); } assert((RegEnc & 0x3FFFF) == RegEnc && "Invalid compact register encoding!"); |