<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hi Logan,<div><br></div><div>Why is this test case a .ll file? Normally, anything at the MC level should have test cases as .s files.</div><div><br></div><div>-Jim</div><div><br></div><div><br><div><div>On Apr 16, 2013, at 5:02 AM, Logan Chien <<a href="mailto:tzuhsiang.chien@gmail.com">tzuhsiang.chien@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Author: logan<br>Date: Tue Apr 16 07:02:21 2013<br>New Revision: 179591<br><br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=179591&view=rev">http://llvm.org/viewvc/llvm-project?rev=179591&view=rev</a><br>Log:<br>Implement ARM unwind opcode assembler.<br><br>Added:<br> llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp<br> llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h<br> llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll<br> llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll<br>Modified:<br> llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp<br> llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h<br> llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt<br> llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll<br> llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll<br> llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll<br><br>Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp?rev=179591&r1=179590&r2=179591&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp?rev=179591&r1=179590&r2=179591&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp (original)<br>+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp Tue Apr 16 07:02:21 2013<br>@@ -13,7 +13,9 @@<br>//<br>//===----------------------------------------------------------------------===//<br><br>+#include "ARMRegisterInfo.h"<br>#include "ARMUnwindOp.h"<br>+#include "ARMUnwindOpAsm.h"<br>#include "llvm/ADT/SmallPtrSet.h"<br>#include "llvm/ADT/Twine.h"<br>#include "llvm/MC/MCAsmBackend.h"<br>@@ -26,6 +28,7 @@<br>#include "llvm/MC/MCExpr.h"<br>#include "llvm/MC/MCInst.h"<br>#include "llvm/MC/MCObjectStreamer.h"<br>+#include "llvm/MC/MCRegisterInfo.h"<br>#include "llvm/MC/MCSection.h"<br>#include "llvm/MC/MCSectionELF.h"<br>#include "llvm/MC/MCStreamer.h"<br>@@ -33,11 +36,15 @@<br>#include "llvm/MC/MCValue.h"<br>#include "llvm/Support/Debug.h"<br>#include "llvm/Support/ELF.h"<br>-#include "llvm/Support/ErrorHandling.h"<br>#include "llvm/Support/raw_ostream.h"<br><br>using namespace llvm;<br><br>+static std::string GetAEABIUnwindPersonalityName(unsigned Index) {<br>+ assert(Index < NUM_PERSONALITY_INDEX && "Invalid personality index");<br>+ return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();<br>+}<br>+<br>namespace {<br><br>/// Extend the generic ELFStreamer class so that it can emit mapping symbols at<br>@@ -57,8 +64,9 @@ public:<br> ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,<br> MCCodeEmitter *Emitter, bool IsThumb)<br> : MCELFStreamer(SK_ARMELFStreamer, Context, TAB, OS, Emitter),<br>- IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None), ExTab(0),<br>- FnStart(0), Personality(0), CantUnwind(false) {}<br>+ IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None) {<br>+ Reset();<br>+ }<br><br> ~ARMELFStreamer() {}<br><br>@@ -194,6 +202,7 @@ private:<br> void Reset();<br><br> void EmitPersonalityFixup(StringRef Name);<br>+ void CollectUnwindOpcodes();<br><br> void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags,<br> SectionKind Kind, const MCSymbol &Fn);<br>@@ -210,9 +219,16 @@ private:<br> MCSymbol *ExTab;<br> MCSymbol *FnStart;<br> const MCSymbol *Personality;<br>+ uint32_t VFPRegSave; // Register mask for {d31-d0}<br>+ uint32_t RegSave; // Register mask for {r15-r0}<br>+ int64_t SPOffset;<br>+ uint16_t FPReg;<br>+ int64_t FPOffset;<br>+ bool UsedFP;<br> bool CantUnwind;<br>+ UnwindOpcodeAssembler UnwindOpAsm;<br>};<br>-}<br>+} // end anonymous namespace<br><br>inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix,<br> unsigned Type,<br>@@ -238,7 +254,7 @@ inline void ARMELFStreamer::SwitchToEHSe<br> } else {<br> EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind);<br> }<br>- assert(EHSection);<br>+ assert(EHSection && "Failed to get the required EH section");<br><br> // Switch to .ARM.extab or .ARM.exidx section<br> SwitchSection(EHSection);<br>@@ -262,10 +278,20 @@ inline void ARMELFStreamer::SwitchToExId<br>}<br><br>void ARMELFStreamer::Reset() {<br>+ const MCRegisterInfo &MRI = getContext().getRegisterInfo();<br>+<br> ExTab = NULL;<br> FnStart = NULL;<br> Personality = NULL;<br>+ VFPRegSave = 0;<br>+ RegSave = 0;<br>+ FPReg = MRI.getEncodingValue(ARM::SP);<br>+ FPOffset = 0;<br>+ SPOffset = 0;<br>+ UsedFP = false;<br> CantUnwind = false;<br>+<br>+ UnwindOpAsm.Reset();<br>}<br><br>// Add the R_ARM_NONE fixup at the same position<br>@@ -284,6 +310,18 @@ void ARMELFStreamer::EmitPersonalityFixu<br> MCFixup::getKindForSize(4, false)));<br>}<br><br>+void ARMELFStreamer::CollectUnwindOpcodes() {<br>+ if (UsedFP) {<br>+ UnwindOpAsm.EmitSetFP(FPReg);<br>+ UnwindOpAsm.EmitSPOffset(-FPOffset);<br>+ } else {<br>+ UnwindOpAsm.EmitSPOffset(SPOffset);<br>+ }<br>+ UnwindOpAsm.EmitVFPRegSave(VFPRegSave);<br>+ UnwindOpAsm.EmitRegSave(RegSave);<br>+ UnwindOpAsm.Finalize();<br>+}<br>+<br>void ARMELFStreamer::EmitFnStart() {<br> assert(FnStart == 0);<br> FnStart = getContext().CreateTempSymbol();<br>@@ -294,35 +332,29 @@ void ARMELFStreamer::EmitFnEnd() {<br> assert(FnStart && ".fnstart must preceeds .fnend");<br><br> // Emit unwind opcodes if there is no .handlerdata directive<br>- int PersonalityIndex = -1;<br> if (!ExTab && !CantUnwind) {<br>- // For __aeabi_unwind_cpp_pr1, we have to emit opcodes in .ARM.extab.<br>- SwitchToExTabSection(*FnStart);<br>-<br>- // Create .ARM.extab label for offset in .ARM.exidx<br>- ExTab = getContext().CreateTempSymbol();<br>- EmitLabel(ExTab);<br>-<br>- PersonalityIndex = 1;<br>-<br>- uint32_t Entry = 0;<br>- uint32_t NumExtraEntryWords = 0;<br>- Entry |= NumExtraEntryWords << 24;<br>- Entry |= (EHT_COMPACT | PersonalityIndex) << 16;<br>-<br>- // TODO: This should be generated according to .save, .vsave, .setfp<br>- // directives. Currently, we are simply generating FINISH opcode.<br>- Entry |= UNWIND_OPCODE_FINISH << 8;<br>- Entry |= UNWIND_OPCODE_FINISH;<br>+ CollectUnwindOpcodes();<br><br>- EmitIntValue(Entry, 4, 0);<br>+ unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex();<br>+ if (PersonalityIndex == AEABI_UNWIND_CPP_PR1 ||<br>+ PersonalityIndex == AEABI_UNWIND_CPP_PR2) {<br>+ // For the __aeabi_unwind_cpp_pr1 and __aeabi_unwind_cpp_pr2, we have to<br>+ // emit the unwind opcodes in the corresponding ".ARM.extab" section, and<br>+ // then emit a reference to these unwind opcodes in the second word of<br>+ // the exception index table entry.<br>+ SwitchToExTabSection(*FnStart);<br>+ ExTab = getContext().CreateTempSymbol();<br>+ EmitLabel(ExTab);<br>+ EmitBytes(UnwindOpAsm.data(), 0);<br>+ }<br> }<br><br> // Emit the exception index table entry<br> SwitchToExIdxSection(*FnStart);<br><br>- if (PersonalityIndex == 1)<br>- EmitPersonalityFixup("__aeabi_unwind_cpp_pr1");<br>+ unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex();<br>+ if (PersonalityIndex < NUM_PERSONALITY_INDEX)<br>+ EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));<br><br> const MCSymbolRefExpr *FnStartRef =<br> MCSymbolRefExpr::Create(FnStart,<br>@@ -333,12 +365,22 @@ void ARMELFStreamer::EmitFnEnd() {<br><br> if (CantUnwind) {<br> EmitIntValue(EXIDX_CANTUNWIND, 4, 0);<br>- } else {<br>+ } else if (ExTab) {<br>+ // Emit a reference to the unwind opcodes in the ".ARM.extab" section.<br> const MCSymbolRefExpr *ExTabEntryRef =<br> MCSymbolRefExpr::Create(ExTab,<br> MCSymbolRefExpr::VK_ARM_PREL31,<br> getContext());<br> EmitValue(ExTabEntryRef, 4, 0);<br>+ } else {<br>+ // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in<br>+ // the second word of exception index table entry. The size of the unwind<br>+ // opcodes should always be 4 bytes.<br>+ assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 &&<br>+ "Compact model must use __aeabi_cpp_unwind_pr0 as personality");<br>+ assert(UnwindOpAsm.size() == 4u &&<br>+ "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4");<br>+ EmitBytes(UnwindOpAsm.data(), 0);<br> }<br><br> // Clean exception handling frame information<br>@@ -368,36 +410,50 @@ void ARMELFStreamer::EmitHandlerData() {<br> EmitValue(PersonalityRef, 4, 0);<br><br> // Emit unwind opcodes<br>- uint32_t Entry = 0;<br>- uint32_t NumExtraEntryWords = 0;<br>-<br>- // TODO: This should be generated according to .save, .vsave, .setfp<br>- // directives. Currently, we are simply generating FINISH opcode.<br>- Entry |= NumExtraEntryWords << 24;<br>- Entry |= UNWIND_OPCODE_FINISH << 16;<br>- Entry |= UNWIND_OPCODE_FINISH << 8;<br>- Entry |= UNWIND_OPCODE_FINISH;<br>-<br>- EmitIntValue(Entry, 4, 0);<br>+ CollectUnwindOpcodes();<br>+ EmitBytes(UnwindOpAsm.data(), 0);<br>}<br><br>void ARMELFStreamer::EmitPersonality(const MCSymbol *Per) {<br> Personality = Per;<br>+ UnwindOpAsm.setPersonality(Per);<br>}<br><br>-void ARMELFStreamer::EmitSetFP(unsigned NewFpReg,<br>- unsigned NewSpReg,<br>+void ARMELFStreamer::EmitSetFP(unsigned NewFPReg,<br>+ unsigned NewSPReg,<br> int64_t Offset) {<br>- // TODO: Not implemented<br>+ assert(SPOffset == 0 &&<br>+ "Current implementation assumes .setfp precedes .pad");<br>+<br>+ const MCRegisterInfo &MRI = getContext().getRegisterInfo();<br>+<br>+ uint16_t NewFPRegEncVal = MRI.getEncodingValue(NewFPReg);<br>+ uint16_t NewSPRegEncVal = MRI.getEncodingValue(NewSPReg);<br>+<br>+ assert((NewSPReg == ARM::SP || NewSPRegEncVal == FPReg) &&<br>+ "the operand of .setfp directive should be either $sp or $fp");<br>+<br>+ UsedFP = true;<br>+ FPReg = NewFPRegEncVal;<br>+ FPOffset = Offset;<br>}<br><br>void ARMELFStreamer::EmitPad(int64_t Offset) {<br>- // TODO: Not implemented<br>+ SPOffset += Offset;<br>}<br><br>void ARMELFStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList,<br> bool IsVector) {<br>- // TODO: Not implemented<br>+ const MCRegisterInfo &MRI = getContext().getRegisterInfo();<br>+<br>+ unsigned Max = IsVector ? 32 : 16;<br>+ uint32_t &RegMask = IsVector ? VFPRegSave : RegSave;<br>+<br>+ for (size_t i = 0; i < RegList.size(); ++i) {<br>+ unsigned Reg = MRI.getEncodingValue(RegList[i]);<br>+ assert(Reg < Max && "Register encoded value out of range");<br>+ RegMask |= 1u << Reg;<br>+ }<br>}<br><br>namespace llvm {<br><br>Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h?rev=179591&r1=179590&r2=179591&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h?rev=179591&r1=179590&r2=179591&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h (original)<br>+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h Tue Apr 16 07:02:21 2013<br>@@ -107,6 +107,19 @@ namespace llvm {<br> UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D8 = 0xd0<br> };<br><br>+ /// ARM-defined Personality Routine Index<br>+ enum ARMPersonalityRoutineIndex {<br>+ // To make the exception handling table become more compact, ARM defined<br>+ // several personality routines in EHABI. There are 3 different<br>+ // personality routines in ARM EHABI currently. It is possible to have 16<br>+ // pre-defined personality routines at most.<br>+ AEABI_UNWIND_CPP_PR0 = 0,<br>+ AEABI_UNWIND_CPP_PR1 = 1,<br>+ AEABI_UNWIND_CPP_PR2 = 2,<br>+<br>+ NUM_PERSONALITY_INDEX<br>+ };<br>+<br>}<br><br>#endif // ARM_UNWIND_OP_H<br><br>Added: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp?rev=179591&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp?rev=179591&view=auto</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp (added)<br>+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp Tue Apr 16 07:02:21 2013<br>@@ -0,0 +1,198 @@<br>+//===-- ARMUnwindOpAsm.cpp - ARM Unwind Opcodes Assembler -------*- C++ -*-===//<br>+//<br>+// The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This file implements the unwind opcode assmebler for ARM exception handling<br>+// table.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "ARMUnwindOpAsm.h"<br>+<br>+#include "ARMUnwindOp.h"<br>+#include "llvm/Support/ErrorHandling.h"<br>+#include "llvm/Support/LEB128.h"<br>+<br>+using namespace llvm;<br>+<br>+void UnwindOpcodeAssembler::EmitRegSave(uint32_t RegSave) {<br>+ if (RegSave == 0u)<br>+ return;<br>+<br>+ // One byte opcode to save register r14 and r11-r4<br>+ if (RegSave & (1u << 4)) {<br>+ // The one byte opcode will always save r4, thus we can't use the one byte<br>+ // opcode when r4 is not in .save directive.<br>+<br>+ // Compute the consecutive registers from r4 to r11.<br>+ uint32_t Range = 0;<br>+ uint32_t Mask = (1u << 4);<br>+ for (uint32_t Bit = (1u << 5); Bit < (1u << 12); Bit <<= 1) {<br>+ if ((RegSave & Bit) == 0u)<br>+ break;<br>+ ++Range;<br>+ Mask |= Bit;<br>+ }<br>+<br>+ // Emit this opcode when the mask covers every registers.<br>+ uint32_t UnmaskedReg = RegSave & 0xfff0u & (~Mask);<br>+ if (UnmaskedReg == 0u) {<br>+ // Pop r[4 : (4 + n)]<br>+ Ops.push_back(UNWIND_OPCODE_POP_REG_RANGE_R4 | Range);<br>+ RegSave &= 0x000fu;<br>+ } else if (UnmaskedReg == (1u << 14)) {<br>+ // Pop r[14] + r[4 : (4 + n)]<br>+ Ops.push_back(UNWIND_OPCODE_POP_REG_RANGE_R4_R14 | Range);<br>+ RegSave &= 0x000fu;<br>+ }<br>+ }<br>+<br>+ // Two bytes opcode to save register r15-r4<br>+ if ((RegSave & 0xfff0u) != 0) {<br>+ uint32_t Op = UNWIND_OPCODE_POP_REG_MASK_R4 | (RegSave >> 4);<br>+ Ops.push_back(static_cast<uint8_t>(Op >> 8));<br>+ Ops.push_back(static_cast<uint8_t>(Op & 0xff));<br>+ }<br>+<br>+ // Opcode to save register r3-r0<br>+ if ((RegSave & 0x000fu) != 0) {<br>+ uint32_t Op = UNWIND_OPCODE_POP_REG_MASK | (RegSave & 0x000fu);<br>+ Ops.push_back(static_cast<uint8_t>(Op >> 8));<br>+ Ops.push_back(static_cast<uint8_t>(Op & 0xff));<br>+ }<br>+}<br>+<br>+/// Emit unwind opcodes for .vsave directives<br>+void UnwindOpcodeAssembler::EmitVFPRegSave(uint32_t VFPRegSave) {<br>+ size_t i = 32;<br>+<br>+ while (i > 16) {<br>+ uint32_t Bit = 1u << (i - 1);<br>+ if ((VFPRegSave & Bit) == 0u) {<br>+ --i;<br>+ continue;<br>+ }<br>+<br>+ uint32_t Range = 0;<br>+<br>+ --i;<br>+ Bit >>= 1;<br>+<br>+ while (i > 16 && (VFPRegSave & Bit)) {<br>+ --i;<br>+ ++Range;<br>+ Bit >>= 1;<br>+ }<br>+<br>+ uint32_t Op =<br>+ UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16 | ((i - 16) << 4) | Range;<br>+ Ops.push_back(static_cast<uint8_t>(Op >> 8));<br>+ Ops.push_back(static_cast<uint8_t>(Op & 0xff));<br>+ }<br>+<br>+ while (i > 0) {<br>+ uint32_t Bit = 1u << (i - 1);<br>+ if ((VFPRegSave & Bit) == 0u) {<br>+ --i;<br>+ continue;<br>+ }<br>+<br>+ uint32_t Range = 0;<br>+<br>+ --i;<br>+ Bit >>= 1;<br>+<br>+ while (i > 0 && (VFPRegSave & Bit)) {<br>+ --i;<br>+ ++Range;<br>+ Bit >>= 1;<br>+ }<br>+<br>+ uint32_t Op = UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD | (i << 4) | Range;<br>+ Ops.push_back(static_cast<uint8_t>(Op >> 8));<br>+ Ops.push_back(static_cast<uint8_t>(Op & 0xff));<br>+ }<br>+}<br>+<br>+/// Emit unwind opcodes for .setfp directives<br>+void UnwindOpcodeAssembler::EmitSetFP(uint16_t FPReg) {<br>+ Ops.push_back(UNWIND_OPCODE_SET_VSP | FPReg);<br>+}<br>+<br>+/// Emit unwind opcodes to update stack pointer<br>+void UnwindOpcodeAssembler::EmitSPOffset(int64_t Offset) {<br>+ if (Offset > 0x200) {<br>+ uint8_t Buff[10];<br>+ size_t Size = encodeULEB128((Offset - 0x204) >> 2, Buff);<br>+ Ops.push_back(UNWIND_OPCODE_INC_VSP_ULEB128);<br>+ Ops.append(Buff, Buff + Size);<br>+ } else if (Offset > 0) {<br>+ if (Offset > 0x100) {<br>+ Ops.push_back(UNWIND_OPCODE_INC_VSP | 0x3fu);<br>+ Offset -= 0x100;<br>+ }<br>+ Ops.push_back(UNWIND_OPCODE_INC_VSP |<br>+ static_cast<uint8_t>((Offset - 4) >> 2));<br>+ } else if (Offset < 0) {<br>+ while (Offset < -0x100) {<br>+ Ops.push_back(UNWIND_OPCODE_DEC_VSP | 0x3fu);<br>+ Offset += 0x100;<br>+ }<br>+ Ops.push_back(UNWIND_OPCODE_DEC_VSP |<br>+ static_cast<uint8_t>(((-Offset) - 4) >> 2));<br>+ }<br>+}<br>+<br>+void UnwindOpcodeAssembler::AddOpcodeSizePrefix(size_t Pos) {<br>+ size_t SizeInWords = (size() + 3) / 4;<br>+ assert(SizeInWords <= 0x100u &&<br>+ "Only 256 additional words are allowed for unwind opcodes");<br>+ Ops[Pos] = static_cast<uint8_t>(SizeInWords - 1);<br>+}<br>+<br>+void UnwindOpcodeAssembler::AddPersonalityIndexPrefix(size_t Pos, unsigned PI) {<br>+ assert(PI < NUM_PERSONALITY_INDEX && "Invalid personality prefix");<br>+ Ops[Pos] = EHT_COMPACT | PI;<br>+}<br>+<br>+void UnwindOpcodeAssembler::EmitFinishOpcodes() {<br>+ for (size_t i = (0x4u - (size() & 0x3u)) & 0x3u; i > 0; --i)<br>+ Ops.push_back(UNWIND_OPCODE_FINISH);<br>+}<br>+<br>+void UnwindOpcodeAssembler::Finalize() {<br>+ if (HasPersonality) {<br>+ // Personality specified by .personality directive<br>+ Offset = 1;<br>+ AddOpcodeSizePrefix(1);<br>+ } else {<br>+ if (getOpcodeSize() <= 3) {<br>+ // __aeabi_unwind_cpp_pr0: [ 0x80 , OP1 , OP2 , OP3 ]<br>+ Offset = 1;<br>+ PersonalityIndex = AEABI_UNWIND_CPP_PR0;<br>+ AddPersonalityIndexPrefix(Offset, PersonalityIndex);<br>+ } else {<br>+ // __aeabi_unwind_cpp_pr1: [ 0x81 , SIZE , OP1 , OP2 , ... ]<br>+ Offset = 0;<br>+ PersonalityIndex = AEABI_UNWIND_CPP_PR1;<br>+ AddPersonalityIndexPrefix(Offset, PersonalityIndex);<br>+ AddOpcodeSizePrefix(1);<br>+ }<br>+ }<br>+<br>+ // Emit the padding finish opcodes if the size() is not multiple of 4.<br>+ EmitFinishOpcodes();<br>+<br>+ // Swap the byte order<br>+ uint8_t *Ptr = Ops.begin() + Offset;<br>+ assert(size() % 4 == 0 && "Final unwind opcodes should align to 4");<br>+ for (size_t i = 0, n = size(); i < n; i += 4) {<br>+ std::swap(Ptr[i], Ptr[i + 3]);<br>+ std::swap(Ptr[i + 1], Ptr[i + 2]);<br>+ }<br>+}<br><br>Added: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h?rev=179591&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h?rev=179591&view=auto</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h (added)<br>+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h Tue Apr 16 07:02:21 2013<br>@@ -0,0 +1,114 @@<br>+//===-- ARMUnwindOpAsm.h - ARM Unwind Opcodes Assembler ---------*- C++ -*-===//<br>+//<br>+// The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This file declares the unwind opcode assmebler for ARM exception handling<br>+// table.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef ARM_UNWIND_OP_ASM_H<br>+#define ARM_UNWIND_OP_ASM_H<br>+<br>+#include "ARMUnwindOp.h"<br>+<br>+#include "llvm/ADT/SmallVector.h"<br>+#include "llvm/ADT/StringRef.h"<br>+#include "llvm/Support/DataTypes.h"<br>+<br>+namespace llvm {<br>+<br>+class MCSymbol;<br>+<br>+class UnwindOpcodeAssembler {<br>+private:<br>+ llvm::SmallVector<uint8_t, 8> Ops;<br>+<br>+ unsigned Offset;<br>+ unsigned PersonalityIndex;<br>+ bool HasPersonality;<br>+<br>+ enum {<br>+ // The number of bytes to be preserved for the size and personality index<br>+ // prefix of unwind opcodes.<br>+ NUM_PRESERVED_PREFIX_BUF = 2<br>+ };<br>+<br>+public:<br>+ UnwindOpcodeAssembler()<br>+ : Ops(NUM_PRESERVED_PREFIX_BUF), Offset(NUM_PRESERVED_PREFIX_BUF),<br>+ PersonalityIndex(NUM_PERSONALITY_INDEX), HasPersonality(0) {<br>+ }<br>+<br>+ /// Reset the unwind opcode assembler.<br>+ void Reset() {<br>+ Ops.resize(NUM_PRESERVED_PREFIX_BUF);<br>+ Offset = NUM_PRESERVED_PREFIX_BUF;<br>+ PersonalityIndex = NUM_PERSONALITY_INDEX;<br>+ HasPersonality = 0;<br>+ }<br>+<br>+ /// Get the size of the payload (including the size byte)<br>+ size_t size() const {<br>+ return Ops.size() - Offset;<br>+ }<br>+<br>+ /// Get the beginning of the payload<br>+ const uint8_t *begin() const {<br>+ return Ops.begin() + Offset;<br>+ }<br>+<br>+ /// Get the payload<br>+ StringRef data() const {<br>+ return StringRef(reinterpret_cast<const char *>(begin()), size());<br>+ }<br>+<br>+ /// Set the personality index<br>+ void setPersonality(const MCSymbol *Per) {<br>+ HasPersonality = 1;<br>+ }<br>+<br>+ /// Get the personality index<br>+ unsigned getPersonalityIndex() const {<br>+ return PersonalityIndex;<br>+ }<br>+<br>+ /// Emit unwind opcodes for .save directives<br>+ void EmitRegSave(uint32_t RegSave);<br>+<br>+ /// Emit unwind opcodes for .vsave directives<br>+ void EmitVFPRegSave(uint32_t VFPRegSave);<br>+<br>+ /// Emit unwind opcodes for .setfp directives<br>+ void EmitSetFP(uint16_t FPReg);<br>+<br>+ /// Emit unwind opcodes to update stack pointer<br>+ void EmitSPOffset(int64_t Offset);<br>+<br>+ /// Finalize the unwind opcode sequence for EmitBytes()<br>+ void Finalize();<br>+<br>+private:<br>+ /// Get the size of the opcodes in bytes.<br>+ size_t getOpcodeSize() const {<br>+ return Ops.size() - NUM_PRESERVED_PREFIX_BUF;<br>+ }<br>+<br>+ /// Add the length prefix to the payload<br>+ void AddOpcodeSizePrefix(size_t Pos);<br>+<br>+ /// Add personality index prefix in some compact format<br>+ void AddPersonalityIndexPrefix(size_t Pos, unsigned PersonalityIndex);<br>+<br>+ /// Fill the words with finish opcode if it is not aligned<br>+ void EmitFinishOpcodes();<br>+};<br>+<br>+} // namespace llvm<br>+<br>+#endif // ARM_UNWIND_OP_ASM_H<br><br>Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt?rev=179591&r1=179590&r2=179591&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt?rev=179591&r1=179590&r2=179591&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt (original)<br>+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt Tue Apr 16 07:02:21 2013<br>@@ -8,6 +8,7 @@ add_llvm_library(LLVMARMDesc<br> ARMMCTargetDesc.cpp<br> ARMMachObjectWriter.cpp<br> ARMELFObjectWriter.cpp<br>+ ARMUnwindOpAsm.cpp<br> )<br>add_dependencies(LLVMARMDesc ARMCommonTableGen)<br><br><br>Added: llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll?rev=179591&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll?rev=179591&view=auto</a><br>==============================================================================<br>--- llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll (added)<br>+++ llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll Tue Apr 16 07:02:21 2013<br>@@ -0,0 +1,49 @@<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -disable-fp-elim -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -s - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK<br>+<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -s - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK-FP-ELIM<br>+<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -disable-fp-elim -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -r - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK-RELOC<br>+<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -r - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK-RELOC<br>+<br>+define void @_Z4testv() {<br>+entry:<br>+ tail call void @_Z15throw_exceptionv()<br>+ ret void<br>+}<br>+<br>+declare void @_Z15throw_exceptionv()<br>+<br>+; CHECK-NOT: section .ARM.extab<br>+; CHECK: section .text<br>+; CHECK-NOT: section .ARM.extab<br>+; CHECK: section .ARM.exidx<br>+; CHECK-NEXT: 0000 00000000 80849b80<br>+; CHECK-NOT: section .ARM.extab<br>+<br>+; CHECK-FP-ELIM-NOT: section .ARM.extab<br>+; CHECK-FP-ELIM: section .text<br>+; CHECK-FP-ELIM-NOT: section .ARM.extab<br>+; CHECK-FP-ELIM: section .ARM.exidx<br>+; CHECK-FP-ELIM-NEXT: 0000 00000000 b0808480<br>+; CHECK-FP-ELIM-NOT: section .ARM.extab<br>+<br>+; CHECK-RELOC: RELOCATION RECORDS FOR [.ARM.exidx]<br>+; CHECK-RELOC-NEXT: 0 R_ARM_PREL31 .text<br>+; CHECK-RELOC-NEXT: 0 R_ARM_NONE __aeabi_unwind_cpp_pr0<br><br>Added: llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll?rev=179591&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll?rev=179591&view=auto</a><br>==============================================================================<br>--- llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll (added)<br>+++ llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll Tue Apr 16 07:02:21 2013<br>@@ -0,0 +1,62 @@<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -disable-fp-elim -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -s - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK<br>+<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -s - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK-FP-ELIM<br>+<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -disable-fp-elim -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -r - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK-RELOC<br>+<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -r - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK-FP-ELIM-RELOC<br>+<br>+define i32 @_Z3addiiiiiiii(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {<br>+entry:<br>+ %add = add nsw i32 %b, %a<br>+ %add1 = add nsw i32 %add, %c<br>+ %add2 = add nsw i32 %add1, %d<br>+ tail call void @_Z15throw_exceptioni(i32 %add2)<br>+ %add3 = add nsw i32 %f, %e<br>+ %add4 = add nsw i32 %add3, %g<br>+ %add5 = add nsw i32 %add4, %h<br>+ tail call void @_Z15throw_exceptioni(i32 %add5)<br>+ %add6 = add nsw i32 %add5, %add2<br>+ ret i32 %add6<br>+}<br>+<br>+declare void @_Z15throw_exceptioni(i32)<br>+<br>+; CHECK-NOT: section .ARM.extab<br>+; CHECK: section .text<br>+; CHECK: section .ARM.extab<br>+; CHECK-NEXT: 0000 419b0181 b0b08384<br>+; CHECK: section .ARM.exidx<br>+; CHECK-NEXT: 0000 00000000 00000000<br>+; CHECK-NOT: section .ARM.extab<br>+<br>+; CHECK-FP-ELIM-NOT: section .ARM.extab<br>+; CHECK-FP-ELIM: section .text<br>+; CHECK-FP-ELIM-NOT: section .ARM.extab<br>+; CHECK-FP-ELIM: section .ARM.exidx<br>+; CHECK-FP-ELIM-NEXT: 0000 00000000 b0838480<br>+; CHECK-FP-ELIM-NOT: section .ARM.extab<br>+<br>+; CHECK-RELOC: RELOCATION RECORDS FOR [.ARM.exidx]<br>+; CHECK-RELOC-NEXT: 0 R_ARM_PREL31 .text<br>+; CHECK-RELOC-NEXT: 0 R_ARM_NONE __aeabi_unwind_cpp_pr1<br>+<br>+; CHECK-FP-ELIM-RELOC: RELOCATION RECORDS FOR [.ARM.exidx]<br>+; CHECK-FP-ELIM-RELOC-NEXT: 0 R_ARM_PREL31 .text<br>+; CHECK-FP-ELIM-RELOC-NEXT: 0 R_ARM_NONE __aeabi_unwind_cpp_pr0<br><br>Modified: llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll?rev=179591&r1=179590&r2=179591&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll?rev=179591&r1=179590&r2=179591&view=diff</a><br>==============================================================================<br>--- llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll (original)<br>+++ llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll Tue Apr 16 07:02:21 2013<br>@@ -72,17 +72,17 @@ declare void @_ZSt9terminatev()<br>; CHECK: Index: 1<br>; CHECK-NEXT: Name: .group (47)<br>; CHECK: SectionData (<br>-; CHECK-NEXT: 0000: 01000000 0A000000 0C000000 0E000000<br>+; CHECK-NEXT: 0000: 01000000 09000000 0B000000 0D000000<br>; CHECK-NEXT: )<br><br>; CHECK: Section {<br>-; CHECK: Index: 10<br>-; CHECK-NEXT: Name: .text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (225)<br>+; CHECK: Index: 9<br>+; CHECK-NEXT: Name: .text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (214)<br><br>; CHECK: Section {<br>-; CHECK: Index: 12<br>-; CHECK-NEXT: Name: .ARM.extab.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (215)<br>+; CHECK: Index: 11<br>+; CHECK-NEXT: Name: .ARM.extab.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (204)<br><br>; CHECK: Section {<br>-; CHECK: Index: 14<br>-; CHECK-NEXT: Name: .ARM.exidx.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (101)<br>+; CHECK: Index: 13<br>+; CHECK-NEXT: Name: .ARM.exidx.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (90)<br><br>Modified: llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll?rev=179591&r1=179590&r2=179591&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll?rev=179591&r1=179590&r2=179591&view=diff</a><br>==============================================================================<br>--- llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll (original)<br>+++ llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll Tue Apr 16 07:02:21 2013<br>@@ -1,8 +1,14 @@<br>-; RUN: llc -mtriple arm-unknown-linux-gnueabi \<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -disable-fp-elim -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -s - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK<br>+<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>; RUN: -filetype=obj -o - %s \<br>; RUN: | llvm-objdump -s - \<br>-; RUN: | FileCheck %s<br>+; RUN: | FileCheck %s --check-prefix=CHECK-FP-ELIM<br><br>define void @_Z4testiiiiiddddd(i32 %u1, i32 %u2, i32 %u3, i32 %u4, i32 %u5, double %v1, double %v2, double %v3, double %v4, double %v5) section ".test_section" {<br>entry:<br>@@ -54,6 +60,12 @@ declare void @_ZSt9terminatev()<br><br>; CHECK: section .test_section<br>; CHECK: section .ARM.extab.test_section<br>-; CHECK-NEXT: 0000 00000000 b0b0b000<br>+; CHECK-NEXT: 0000 00000000 c9409b01 b0818484<br>; CHECK: section .ARM.exidx.test_section<br>; CHECK-NEXT: 0000 00000000 00000000<br>+<br>+; CHECK-FP-ELIM: section .test_section<br>+; CHECK-FP-ELIM: section .ARM.extab.test_section<br>+; CHECK-FP-ELIM-NEXT: 0000 00000000 84c90501 b0b0b0a8<br>+; CHECK-FP-ELIM: section .ARM.exidx.test_section<br>+; CHECK-FP-ELIM-NEXT: 0000 00000000 00000000<br><br>Modified: llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll?rev=179591&r1=179590&r2=179591&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll?rev=179591&r1=179590&r2=179591&view=diff</a><br>==============================================================================<br>--- llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll (original)<br>+++ llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll Tue Apr 16 07:02:21 2013<br>@@ -1,8 +1,14 @@<br>-; RUN: llc -mtriple arm-unknown-linux-gnueabi \<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>+; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>+; RUN: -disable-fp-elim -filetype=obj -o - %s \<br>+; RUN: | llvm-objdump -s - \<br>+; RUN: | FileCheck %s --check-prefix=CHECK<br>+<br>+; RUN: llc -mtriple armv7-unknown-linux-gnueabi \<br>; RUN: -arm-enable-ehabi -arm-enable-ehabi-descriptors \<br>; RUN: -filetype=obj -o - %s \<br>; RUN: | llvm-objdump -s - \<br>-; RUN: | FileCheck %s<br>+; RUN: | FileCheck %s --check-prefix=CHECK-FP-ELIM<br><br>define void @_Z4testiiiiiddddd(i32 %u1, i32 %u2, i32 %u3, i32 %u4, i32 %u5, double %v1, double %v2, double %v3, double %v4, double %v5) {<br>entry:<br>@@ -54,6 +60,12 @@ declare void @_ZSt9terminatev()<br><br>; CHECK: section .text<br>; CHECK: section .ARM.extab<br>-; CHECK-NEXT: 0000 00000000 b0b0b000<br>+; CHECK-NEXT: 0000 00000000 c9409b01 b0818484<br>; CHECK: section .ARM.exidx<br>; CHECK-NEXT: 0000 00000000 00000000<br>+<br>+; CHECK-FP-ELIM: section .text<br>+; CHECK-FP-ELIM: section .ARM.extab<br>+; CHECK-FP-ELIM-NEXT: 0000 00000000 84c90501 b0b0b0a8<br>+; CHECK-FP-ELIM: section .ARM.exidx<br>+; CHECK-FP-ELIM-NEXT: 0000 00000000 00000000<br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a></div></blockquote></div><br></div></body></html>