<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Bruno,<div><br></div><div>This is causing clang test failures.</div><div><br></div><div><span class="Apple-style-span" style="font-family: Times; "><pre style="font-family: 'Courier New', courier, monotype; "><span class="stdout" style="font-family: 'Courier New', courier, monotype; color: black; ">LLVM :: CodeGen/ARM/ldr_post.ll
LLVM :: CodeGen/ARM/ldst-f32-2-i32.ll
LLVM :: CodeGen/ARM/str_pre-2.ll</span></pre></span><div>Can you take a look ?</div><div>Thanks,</div><div>-</div><div>Devang</div><div><br></div><div><div>On Mar 31, 2011, at 7:52 AM, Bruno Cardoso Lopes wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: bruno<br>Date: Thu Mar 31 09:52:28 2011<br>New Revision: 128632<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=128632&view=rev">http://llvm.org/viewvc/llvm-project?rev=128632&view=rev</a><br>Log:<br>Reapply r128585 without generating a lib depedency cycle. An updated log:<br><br>- Implement asm parsing support for LDRT, LDRBT, STRT, STRBT and<br>  {STR,LDC}{2}_{PRE,POST} fixing the encoding wherever is possible.<br>- Move all instructions which use am2offset without a pattern to use<br>  addrmode2.<br>- Add a new encoding bit to describe the index mode used and teach<br>  printAddrMode2Operand to check by the addressing mode which index<br>  mode to print.<br>- Testcases<br><br>Added:<br>    llvm/trunk/test/MC/ARM/arm_addrmode2.s<br>Modified:<br>    llvm/trunk/lib/Target/ARM/ARMAddressingModes.h<br>    llvm/trunk/lib/Target/ARM/ARMBaseInfo.h<br>    llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h<br>    llvm/trunk/lib/Target/ARM/ARMInstrFormats.td<br>    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td<br>    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp<br>    llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp<br>    llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp<br>    llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h<br><br>Modified: llvm/trunk/lib/Target/ARM/ARMAddressingModes.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAddressingModes.h?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAddressingModes.h?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMAddressingModes.h (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMAddressingModes.h Thu Mar 31 09:52:28 2011<br>@@ -408,16 +408,18 @@<br>   //<br>   // The first operand is always a Reg.  The second operand is a reg if in<br>   // reg/reg form, otherwise it's reg#0.  The third field encodes the operation<br>-  // in bit 12, the immediate in bits 0-11, and the shift op in 13-15.<br>+  // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The<br>+  // forth operand 16-17 encodes the index mode.<br>   //<br>   // If this addressing mode is a frame index (before prolog/epilog insertion<br>   // and code rewriting), this operand will have the form:  FI#, reg0, <offs><br>   // with no shift amount for the frame offset.<br>   //<br>-  static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) {<br>+  static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,<br>+                                   unsigned IdxMode = 0) {<br>     assert(Imm12 < (1 << 12) && "Imm too large!");<br>     bool isSub = Opc == sub;<br>-    return Imm12 | ((int)isSub << 12) | (SO << 13);<br>+    return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;<br>   }<br>   static inline unsigned getAM2Offset(unsigned AM2Opc) {<br>     return AM2Opc & ((1 << 12)-1);<br>@@ -426,7 +428,10 @@<br>     return ((AM2Opc >> 12) & 1) ? sub : add;<br>   }<br>   static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {<br>-    return (ShiftOpc)(AM2Opc >> 13);<br>+    return (ShiftOpc)((AM2Opc >> 13) & 7);<br>+  }<br>+  static inline unsigned getAM2IdxMode(unsigned AM2Opc) {<br>+    return (AM2Opc >> 16);<br>   }<br><br><br><br>Modified: llvm/trunk/lib/Target/ARM/ARMBaseInfo.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInfo.h?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInfo.h?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMBaseInfo.h (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMBaseInfo.h Thu Mar 31 09:52:28 2011<br>@@ -200,6 +200,59 @@<br> }<br><br> namespace ARMII {<br>+<br>+  /// ARM Index Modes<br>+  enum IndexMode {<br>+    IndexModeNone  = 0,<br>+    IndexModePre   = 1,<br>+    IndexModePost  = 2,<br>+    IndexModeUpd   = 3<br>+  };<br>+<br>+  /// ARM Addressing Modes<br>+  enum AddrMode {<br>+    AddrModeNone    = 0,<br>+    AddrMode1       = 1,<br>+    AddrMode2       = 2,<br>+    AddrMode3       = 3,<br>+    AddrMode4       = 4,<br>+    AddrMode5       = 5,<br>+    AddrMode6       = 6,<br>+    AddrModeT1_1    = 7,<br>+    AddrModeT1_2    = 8,<br>+    AddrModeT1_4    = 9,<br>+    AddrModeT1_s    = 10, // i8 * 4 for pc and sp relative data<br>+    AddrModeT2_i12  = 11,<br>+    AddrModeT2_i8   = 12,<br>+    AddrModeT2_so   = 13,<br>+    AddrModeT2_pc   = 14, // +/- i12 for pc relative data<br>+    AddrModeT2_i8s4 = 15, // i8 * 4<br>+    AddrMode_i12    = 16<br>+  };<br>+<br>+  inline static const char *AddrModeToString(AddrMode addrmode) {<br>+    switch (addrmode) {<br>+    default: llvm_unreachable("Unknown memory operation");<br>+    case AddrModeNone:    return "AddrModeNone";<br>+    case AddrMode1:       return "AddrMode1";<br>+    case AddrMode2:       return "AddrMode2";<br>+    case AddrMode3:       return "AddrMode3";<br>+    case AddrMode4:       return "AddrMode4";<br>+    case AddrMode5:       return "AddrMode5";<br>+    case AddrMode6:       return "AddrMode6";<br>+    case AddrModeT1_1:    return "AddrModeT1_1";<br>+    case AddrModeT1_2:    return "AddrModeT1_2";<br>+    case AddrModeT1_4:    return "AddrModeT1_4";<br>+    case AddrModeT1_s:    return "AddrModeT1_s";<br>+    case AddrModeT2_i12:  return "AddrModeT2_i12";<br>+    case AddrModeT2_i8:   return "AddrModeT2_i8";<br>+    case AddrModeT2_so:   return "AddrModeT2_so";<br>+    case AddrModeT2_pc:   return "AddrModeT2_pc";<br>+    case AddrModeT2_i8s4: return "AddrModeT2_i8s4";<br>+    case AddrMode_i12:    return "AddrMode_i12";<br>+    }<br>+  }<br>+<br>   /// Target Operand Flag enum.<br>   enum TOF {<br>     //===------------------------------------------------------------------===//<br><br>Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Thu Mar 31 09:52:28 2011<br>@@ -34,25 +34,7 @@<br><br>     //===------------------------------------------------------------------===//<br>     // This four-bit field describes the addressing mode used.<br>-<br>-    AddrModeMask  = 0x1f,<br>-    AddrModeNone    = 0,<br>-    AddrMode1       = 1,<br>-    AddrMode2       = 2,<br>-    AddrMode3       = 3,<br>-    AddrMode4       = 4,<br>-    AddrMode5       = 5,<br>-    AddrMode6       = 6,<br>-    AddrModeT1_1    = 7,<br>-    AddrModeT1_2    = 8,<br>-    AddrModeT1_4    = 9,<br>-    AddrModeT1_s    = 10, // i8 * 4 for pc and sp relative data<br>-    AddrModeT2_i12  = 11,<br>-    AddrModeT2_i8   = 12,<br>-    AddrModeT2_so   = 13,<br>-    AddrModeT2_pc   = 14, // +/- i12 for pc relative data<br>-    AddrModeT2_i8s4 = 15, // i8 * 4<br>-    AddrMode_i12    = 16,<br>+    AddrModeMask  = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h<br><br>     // Size* - Flags to keep track of the size of an instruction.<br>     SizeShift     = 5,<br>@@ -64,11 +46,9 @@<br><br>     // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load<br>     // and store ops only.  Generic "updating" flag is used for ld/st multiple.<br>+    // The index mode enums are declared in ARMBaseInfo.h<br>     IndexModeShift = 8,<br>     IndexModeMask  = 3 << IndexModeShift,<br>-    IndexModePre   = 1,<br>-    IndexModePost  = 2,<br>-    IndexModeUpd   = 3,<br><br>     //===------------------------------------------------------------------===//<br>     // Instruction encoding formats.<br><br>Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Thu Mar 31 09:52:28 2011<br>@@ -515,15 +515,15 @@<br>   : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,<br>                pattern> {<br>   // AM2 store w/ two operands: (GPR, am2offset)<br>+  // {17-14}  Rn<br>   // {13}     1 == Rm, 0 == imm12<br>   // {12}     isAdd<br>   // {11-0}   imm12/Rm<br>-  bits<14> offset;<br>-  bits<4> Rn;<br>-  let Inst{25} = offset{13};<br>-  let Inst{23} = offset{12};<br>-  let Inst{19-16} = Rn;<br>-  let Inst{11-0} = offset{11-0};<br>+  bits<18> addr;<br>+  let Inst{25} = addr{13};<br>+  let Inst{23} = addr{12};<br>+  let Inst{19-16} = addr{17-14};<br>+  let Inst{11-0} = addr{11-0};<br> }<br><br> // addrmode3 instructions<br><br>Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Thu Mar 31 09:52:28 2011<br>@@ -498,6 +498,12 @@<br>   let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);<br> }<br><br>+def MemMode2AsmOperand : AsmOperandClass {<br>+  let Name = "MemMode2";<br>+  let SuperClasses = [];<br>+  let ParserMethod = "tryParseMemMode2Operand";<br>+}<br>+<br> // addrmode2 := reg +/- imm12<br> //           := reg +/- reg shop imm<br> //<br>@@ -505,6 +511,7 @@<br>                 ComplexPattern<i32, 3, "SelectAddrMode2", []> {<br>   let EncoderMethod = "getAddrMode2OpValue";<br>   let PrintMethod = "printAddrMode2Operand";<br>+  let ParserMatchClass = MemMode2AsmOperand;<br>   let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);<br> }<br><br>@@ -1656,20 +1663,21 @@<br>     let Inst{23} = addr{12};<br>     let Inst{19-16} = addr{17-14};<br>     let Inst{11-0} = addr{11-0};<br>+    let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br>   }<br>   def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),<br>-                      (ins GPR:$Rn, am2offset:$offset),<br>-                      IndexModePost, LdFrm, itin,<br>-                      opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {<br>+                      (ins addrmode2:$addr), IndexModePost, LdFrm, itin,<br>+                      opc, "\t$Rt, $addr", "$addr.base = $Rn_wb", []> {<br>+    // {17-14}  Rn<br>     // {13}     1 == Rm, 0 == imm12<br>     // {12}     isAdd<br>     // {11-0}   imm12/Rm<br>-    bits<14> offset;<br>-    bits<4> Rn;<br>-    let Inst{25} = offset{13};<br>-    let Inst{23} = offset{12};<br>-    let Inst{19-16} = Rn;<br>-    let Inst{11-0} = offset{11-0};<br>+    bits<18> addr;<br>+    let Inst{25} = addr{13};<br>+    let Inst{23} = addr{12};<br>+    let Inst{19-16} = addr{17-14};<br>+    let Inst{11-0} = addr{11-0};<br>+    let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br>   }<br> }<br><br>@@ -1714,17 +1722,35 @@<br><br> // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.<br> let mayLoad = 1, neverHasSideEffects = 1 in {<br>-def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$dst, GPR:$base_wb),<br>-                   (ins GPR:$base, am2offset:$offset), IndexModePost,<br>-                   LdFrm, IIC_iLoad_ru,<br>-                   "ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {<br>+def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),<br>+                   (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,<br>+                   "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {<br>+  // {17-14}  Rn<br>+  // {13}     1 == Rm, 0 == imm12<br>+  // {12}     isAdd<br>+  // {11-0}   imm12/Rm<br>+  bits<18> addr;<br>+  let Inst{25} = addr{13};<br>+  let Inst{23} = addr{12};<br>   let Inst{21} = 1; // overwrite<br>-}<br>-def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$dst, GPR:$base_wb),<br>-                  (ins GPR:$base, am2offset:$offset), IndexModePost,<br>-                  LdFrm, IIC_iLoad_bh_ru,<br>-                  "ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {<br>+  let Inst{19-16} = addr{17-14};<br>+  let Inst{11-0} = addr{11-0};<br>+  let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br>+}<br>+def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),<br>+                  (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru,<br>+                  "ldrbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {<br>+  // {17-14}  Rn<br>+  // {13}     1 == Rm, 0 == imm12<br>+  // {12}     isAdd<br>+  // {11-0}   imm12/Rm<br>+  bits<18> addr;<br>+  let Inst{25} = addr{13};<br>+  let Inst{23} = addr{12};<br>   let Inst{21} = 1; // overwrite<br>+  let Inst{19-16} = addr{17-14};<br>+  let Inst{11-0} = addr{11-0};<br>+  let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br> }<br> def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),<br>                  (ins GPR:$base, am3offset:$offset), IndexModePost,<br>@@ -1818,20 +1844,20 @@<br><br> // STRT, STRBT, and STRHT are for disassembly only.<br><br>-def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb),<br>-                    (ins GPR:$Rt, GPR:$Rn,am2offset:$offset),<br>+def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),<br>                     IndexModePost, StFrm, IIC_iStore_ru,<br>-                    "strt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",<br>+                    "strt", "\t$Rt, $addr", "$addr.base = $Rn_wb",<br>                     [/* For disassembly only; pattern left blank */]> {<br>   let Inst{21} = 1; // overwrite<br>+  let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";<br> }<br><br>-def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb),<br>-                     (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),<br>+def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),<br>                      IndexModePost, StFrm, IIC_iStore_bh_ru,<br>-                     "strbt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",<br>+                     "strbt", "\t$Rt, $addr", "$addr.base = $Rn_wb",<br>                      [/* For disassembly only; pattern left blank */]> {<br>   let Inst{21} = 1; // overwrite<br>+  let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";<br> }<br><br> def STRHT: AI3sthpo<(outs GPR:$base_wb),<br>@@ -3391,8 +3417,9 @@<br>   let Inst{23-20} = opc1;<br> }<br><br>-class ACI<dag oops, dag iops, string opc, string asm><br>-  : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, NoItinerary,<br>+class ACI<dag oops, dag iops, string opc, string asm,<br>+          IndexMode im = IndexModeNone><br>+  : I<oops, iops, AddrModeNone, Size4Bytes, im, BrFrm, NoItinerary,<br>       opc, asm, "", [/* For disassembly only; pattern left blank */]> {<br>   let Inst{27-25} = 0b110;<br> }<br>@@ -3411,7 +3438,7 @@<br><br>   def _PRE : ACI<(outs),<br>       (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>-      opc, "\tp$cop, cr$CRd, $addr!"> {<br>+      opc, "\tp$cop, cr$CRd, $addr!", IndexModePre> {<br>     let Inst{31-28} = op31_28;<br>     let Inst{24} = 1; // P = 1<br>     let Inst{21} = 1; // W = 1<br>@@ -3420,8 +3447,8 @@<br>   }<br><br>   def _POST : ACI<(outs),<br>-      (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),<br>-      opc, "\tp$cop, cr$CRd, [$base], $offset"> {<br>+      (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>+      opc, "\tp$cop, cr$CRd, $addr", IndexModePost> {<br>     let Inst{31-28} = op31_28;<br>     let Inst{24} = 0; // P = 0<br>     let Inst{21} = 1; // W = 1<br>@@ -3452,7 +3479,7 @@<br><br>   def L_PRE : ACI<(outs),<br>       (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>-      !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!"> {<br>+      !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!", IndexModePre> {<br>     let Inst{31-28} = op31_28;<br>     let Inst{24} = 1; // P = 1<br>     let Inst{21} = 1; // W = 1<br>@@ -3461,8 +3488,8 @@<br>   }<br><br>   def L_POST : ACI<(outs),<br>-      (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),<br>-      !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $offset"> {<br>+      (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>+      !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr", IndexModePost> {<br>     let Inst{31-28} = op31_28;<br>     let Inst{24} = 0; // P = 0<br>     let Inst{21} = 1; // W = 1<br><br>Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)<br>+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Thu Mar 31 09:52:28 2011<br>@@ -48,7 +48,8 @@<br>   bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);<br>   bool TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);<br>   bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);<br>-  bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);<br>+  bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,<br>+                   ARMII::AddrMode AddrMode);<br>   bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);<br>   bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);<br>   const MCExpr *ApplyPrefixToExpr(const MCExpr *E,<br>@@ -95,6 +96,14 @@<br>     SmallVectorImpl<MCParsedAsmOperand*>&);<br>   OperandMatchResultTy tryParseMSRMaskOperand(<br>     SmallVectorImpl<MCParsedAsmOperand*>&);<br>+  OperandMatchResultTy tryParseMemMode2Operand(<br>+    SmallVectorImpl<MCParsedAsmOperand*>&);<br>+<br>+  // Asm Match Converter Methods<br>+  bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>+                                  const SmallVectorImpl<MCParsedAsmOperand*> &);<br>+  bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>+                                  const SmallVectorImpl<MCParsedAsmOperand*> &);<br><br> public:<br>   ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)<br>@@ -172,6 +181,7 @@<br><br>     /// Combined record for all forms of ARM address expressions.<br>     struct {<br>+      ARMII::AddrMode AddrMode;<br>       unsigned BaseRegNum;<br>       union {<br>         unsigned RegNum;     ///< Offset register num, when OffsetIsReg.<br>@@ -293,7 +303,9 @@<br><br>   /// @name Memory Operand Accessors<br>   /// @{<br>-<br>+  ARMII::AddrMode getMemAddrMode() const {<br>+    return Mem.AddrMode;<br>+  }<br>   unsigned getMemBaseRegNum() const {<br>     return Mem.BaseRegNum;<br>   }<br>@@ -338,6 +350,27 @@<br>   bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }<br>   bool isMemory() const { return Kind == Memory; }<br>   bool isShifter() const { return Kind == Shifter; }<br>+  bool isMemMode2() const {<br>+    if (getMemAddrMode() != ARMII::AddrMode2)<br>+      return false;<br>+<br>+    if (getMemOffsetIsReg())<br>+      return true;<br>+<br>+    if (getMemNegative() &&<br>+        !(getMemPostindexed() || getMemPreindexed()))<br>+      return false;<br>+<br>+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());<br>+    if (!CE) return false;<br>+    int64_t Value = CE->getValue();<br>+<br>+    // The offset must be in the range 0-4095 (imm12).<br>+    if (Value > 4095 || Value < -4095)<br>+      return false;<br>+<br>+    return true;<br>+  }<br>   bool isMemMode5() const {<br>     if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||<br>         getMemNegative())<br>@@ -465,6 +498,47 @@<br>            "No offset operand support in mode 7");<br>   }<br><br>+  void addMemMode2Operands(MCInst &Inst, unsigned N) const {<br>+    assert(isMemMode2() && "Invalid mode or number of operands!");<br>+    Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));<br>+    unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);<br>+<br>+    if (getMemOffsetIsReg()) {<br>+      Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));<br>+<br>+      ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;<br>+      ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift;<br>+      int64_t ShiftAmount = 0;<br>+<br>+      if (getMemOffsetRegShifted()) {<br>+        ShOpc = getMemShiftType();<br>+        const MCConstantExpr *CE =<br>+                   dyn_cast<MCConstantExpr>(getMemShiftAmount());<br>+        ShiftAmount = CE->getValue();<br>+      }<br>+<br>+      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount,<br>+                                           ShOpc, IdxMode)));<br>+      return;<br>+    }<br>+<br>+    // Create a operand placeholder to always yield the same number of operands.<br>+    Inst.addOperand(MCOperand::CreateReg(0));<br>+<br>+    // FIXME: #-0 is encoded differently than #0. Does the parser preserve<br>+    // the difference?<br>+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());<br>+    assert(CE && "Non-constant mode 2 offset operand!");<br>+    int64_t Offset = CE->getValue();<br>+<br>+    if (Offset >= 0)<br>+      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add,<br>+                                           Offset, ARM_AM::no_shift, IdxMode)));<br>+    else<br>+      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub,<br>+                                          -Offset, ARM_AM::no_shift, IdxMode)));<br>+  }<br>+<br>   void addMemMode5Operands(MCInst &Inst, unsigned N) const {<br>     assert(N == 2 && isMemMode5() && "Invalid number of operands!");<br><br>@@ -599,9 +673,9 @@<br>     return Op;<br>   }<br><br>-  static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,<br>-                               const MCExpr *Offset, int OffsetRegNum,<br>-                               bool OffsetRegShifted,<br>+  static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum,<br>+                               bool OffsetIsReg, const MCExpr *Offset,<br>+                               int OffsetRegNum, bool OffsetRegShifted,<br>                                enum ARM_AM::ShiftOpc ShiftType,<br>                                const MCExpr *ShiftAmount, bool Preindexed,<br>                                bool Postindexed, bool Negative, bool Writeback,<br>@@ -618,6 +692,7 @@<br>            "Cannot have expression offset and register offset!");<br><br>     ARMOperand *Op = new ARMOperand(Memory);<br>+    Op->Mem.AddrMode = AddrMode;<br>     Op->Mem.BaseRegNum = BaseRegNum;<br>     Op->Mem.OffsetIsReg = OffsetIsReg;<br>     if (OffsetIsReg)<br>@@ -689,7 +764,8 @@<br>     break;<br>   case Memory:<br>     OS << "<memory "<br>-       << "base:" << getMemBaseRegNum();<br>+       << "am:" << ARMII::AddrModeToString(getMemAddrMode())<br>+       << " base:" << getMemBaseRegNum();<br>     if (getMemOffsetIsReg()) {<br>       OS << " offset:<register " << getMemOffsetRegNum();<br>       if (getMemOffsetRegShifted()) {<br>@@ -1132,13 +1208,57 @@<br>   return MatchOperand_Success;<br> }<br><br>+/// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand.<br>+ARMAsmParser::OperandMatchResultTy ARMAsmParser::<br>+tryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>+  SMLoc S = Parser.getTok().getLoc();<br>+  const AsmToken &Tok = Parser.getTok();<br>+  assert(<a href="http://Tok.is">Tok.is</a>(AsmToken::LBrac) && "Token is not a \"[\"");<br>+<br>+  if (ParseMemory(Operands, ARMII::AddrMode2))<br>+    return MatchOperand_NoMatch;<br>+<br>+  return MatchOperand_Success;<br>+}<br>+<br>+/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.<br>+/// Needed here because the Asm Gen Matcher can't handle properly tied operands<br>+/// when they refer multiple MIOperands inside a single one.<br>+bool ARMAsmParser::<br>+CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>+                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>+  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);<br>+<br>+  // Create a writeback register dummy placeholder.<br>+  Inst.addOperand(MCOperand::CreateImm(0));<br>+<br>+  ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);<br>+  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);<br>+  return true;<br>+}<br>+<br>+/// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.<br>+/// Needed here because the Asm Gen Matcher can't handle properly tied operands<br>+/// when they refer multiple MIOperands inside a single one.<br>+bool ARMAsmParser::<br>+CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>+                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>+  // Create a writeback register dummy placeholder.<br>+  Inst.addOperand(MCOperand::CreateImm(0));<br>+  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);<br>+  ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);<br>+  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);<br>+  return true;<br>+}<br>+<br> /// Parse an ARM memory expression, return false if successful else return true<br> /// or an error.  The first token must be a '[' when called.<br> ///<br> /// TODO Only preindexing and postindexing addressing are started, unindexed<br> /// with option, etc are still to do.<br> bool ARMAsmParser::<br>-ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>+ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,<br>+            ARMII::AddrMode AddrMode = ARMII::AddrModeNone) {<br>   SMLoc S, E;<br>   assert(Parser.getTok().is(AsmToken::LBrac) &&<br>          "Token is not a Left Bracket");<br>@@ -1196,6 +1316,9 @@<br>                                      ExclaimTok.getLoc());<br>       Writeback = true;<br>       Parser.Lex(); // Eat exclaim token<br>+    } else { // In addressing mode 2, pre-indexed mode always end with "!"<br>+      if (AddrMode == ARMII::AddrMode2)<br>+        Preindexed = false;<br>     }<br>   } else {<br>     // The "[Rn" we have so far was not followed by a comma.<br>@@ -1231,11 +1354,10 @@<br>       Offset = MCConstantExpr::Create(0, getContext());<br>   }<br><br>-  Operands.push_back(ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset,<br>-                                           OffsetRegNum, OffsetRegShifted,<br>-                                           ShiftType, ShiftAmount, Preindexed,<br>-                                           Postindexed, Negative, Writeback,<br>-                                           S, E));<br>+  Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,<br>+                                     Offset, OffsetRegNum, OffsetRegShifted,<br>+                                     ShiftType, ShiftAmount, Preindexed,<br>+                                     Postindexed, Negative, Writeback, S, E));<br>   if (WBOp)<br>     Operands.push_back(WBOp);<br><br><br>Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original)<br>+++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Thu Mar 31 09:52:28 2011<br>@@ -643,8 +643,11 @@<br>     if (PW) {<br>       MI.addOperand(MCOperand::CreateReg(0));<br>       ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;<br>+      const TargetInstrDesc &TID = ARMInsts[Opcode];<br>+      unsigned IndexMode =<br>+                  (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;<br>       unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2,<br>-                                          ARM_AM::no_shift);<br>+                                          ARM_AM::no_shift, IndexMode);<br>       MI.addOperand(MCOperand::CreateImm(Offset));<br>       OpIdx = 5;<br>     } else {<br>@@ -1073,6 +1076,8 @@<br>     return false;<br><br>   ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;<br>+  unsigned IndexMode =<br>+               (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;<br>   if (getIBit(insn) == 0) {<br>     // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2).<br>     // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already<br>@@ -1084,7 +1089,8 @@<br><br>     // Disassemble the 12-bit immediate offset.<br>     unsigned Imm12 = slice(insn, 11, 0);<br>-    unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift);<br>+    unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift,<br>+                                        IndexMode);<br>     MI.addOperand(MCOperand::CreateImm(Offset));<br>     OpIdx += 1;<br>   } else {<br>@@ -1099,7 +1105,7 @@<br>     // A8.4.1.  Possible rrx or shift amount of 32...<br>     getImmShiftSE(ShOp, ShImm);<br>     MI.addOperand(MCOperand::CreateImm(<br>-                    ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp)));<br>+                    ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp, IndexMode)));<br>     OpIdx += 2;<br>   }<br><br><br>Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (original)<br>+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp Thu Mar 31 09:52:28 2011<br>@@ -181,18 +181,12 @@<br>   }<br> }<br><br>-<br>-void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,<br>-                                           raw_ostream &O) {<br>+void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,<br>+                                                raw_ostream &O) {<br>   const MCOperand &MO1 = MI->getOperand(Op);<br>   const MCOperand &MO2 = MI->getOperand(Op+1);<br>   const MCOperand &MO3 = MI->getOperand(Op+2);<br><br>-  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.<br>-    printOperand(MI, Op, O);<br>-    return;<br>-  }<br>-<br>   O << "[" << getRegisterName(MO1.getReg());<br><br>   if (!MO2.getReg()) {<br>@@ -215,6 +209,50 @@<br>   O << "]";<br> }<br><br>+void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,<br>+                                         raw_ostream &O) {<br>+  const MCOperand &MO1 = MI->getOperand(Op);<br>+  const MCOperand &MO2 = MI->getOperand(Op+1);<br>+  const MCOperand &MO3 = MI->getOperand(Op+2);<br>+<br>+  O << "[" << getRegisterName(MO1.getReg()) << "], ";<br>+<br>+  if (!MO2.getReg()) {<br>+    unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());<br>+    O << '#'<br>+      << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))<br>+      << ImmOffs;<br>+    return;<br>+  }<br>+<br>+  O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))<br>+    << getRegisterName(MO2.getReg());<br>+<br>+  if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))<br>+    O << ", "<br>+    << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))<br>+    << " #" << ShImm;<br>+}<br>+<br>+void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,<br>+                                           raw_ostream &O) {<br>+  const MCOperand &MO1 = MI->getOperand(Op);<br>+<br>+  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.<br>+    printOperand(MI, Op, O);<br>+    return;<br>+  }<br>+<br>+  const MCOperand &MO3 = MI->getOperand(Op+2);<br>+  unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());<br>+<br>+  if (IdxMode == ARMII::IndexModePost) {<br>+    printAM2PostIndexOp(MI, Op, O);<br>+    return;<br>+  }<br>+  printAM2PreOrOffsetIndexOp(MI, Op, O);<br>+}<br>+<br> void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,<br>                                                  unsigned OpNum,<br>                                                  raw_ostream &O) {<br><br>Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h (original)<br>+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h Thu Mar 31 09:52:28 2011<br>@@ -42,7 +42,11 @@<br>   void printSOImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br><br>   void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>+<br>   void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>+  void printAM2PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>+  void printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,<br>+                                  raw_ostream &O);<br>   void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum,<br>                                    raw_ostream &O);<br>   void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br><br>Added: llvm/trunk/test/MC/ARM/arm_addrmode2.s<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm_addrmode2.s?rev=128632&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm_addrmode2.s?rev=128632&view=auto</a><br>==============================================================================<br>--- llvm/trunk/test/MC/ARM/arm_addrmode2.s (added)<br>+++ llvm/trunk/test/MC/ARM/arm_addrmode2.s Thu Mar 31 09:52:28 2011<br>@@ -0,0 +1,38 @@<br>+@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s<br>+<br>+@ Post-indexed<br>+@ CHECK: ldrt  r1, [r0], r2 @ encoding: [0x02,0x10,0xb0,0xe6]<br>+@ CHECK: ldrt  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xb0,0xe6]<br>+@ CHECK: ldrt  r1, [r0], #4 @ encoding: [0x04,0x10,0xb0,0xe4]<br>+@ CHECK: ldrbt  r1, [r0], r2 @ encoding: [0x02,0x10,0xf0,0xe6]<br>+@ CHECK: ldrbt  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xf0,0xe6]<br>+@ CHECK: ldrbt  r1, [r0], #4 @ encoding: [0x04,0x10,0xf0,0xe4]<br>+@ CHECK: strt  r1, [r0], r2 @ encoding: [0x02,0x10,0xa0,0xe6]<br>+@ CHECK: strt  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xa0,0xe6]<br>+@ CHECK: strt  r1, [r0], #4 @ encoding: [0x04,0x10,0xa0,0xe4]<br>+@ CHECK: strbt  r1, [r0], r2 @ encoding: [0x02,0x10,0xe0,0xe6]<br>+@ CHECK: strbt  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xe0,0xe6]<br>+@ CHECK: strbt  r1, [r0], #4 @ encoding: [0x04,0x10,0xe0,0xe4]<br>+@ CHECK: ldr  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0x90,0xe6]<br>+@ CHECK: ldrb  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xd0,0xe6]<br>+        ldrt  r1, [r0], r2<br>+        ldrt  r1, [r0], r2, lsr #3<br>+        ldrt  r1, [r0], #4<br>+        ldrbt  r1, [r0], r2<br>+        ldrbt  r1, [r0], r2, lsr #3<br>+        ldrbt  r1, [r0], #4<br>+        strt  r1, [r0], r2<br>+        strt  r1, [r0], r2, lsr #3<br>+        strt  r1, [r0], #4<br>+        strbt  r1, [r0], r2<br>+        strbt  r1, [r0], r2, lsr #3<br>+        strbt  r1, [r0], #4<br>+        ldr  r1, [r0], r2, lsr #3<br>+        ldrb  r1, [r0], r2, lsr #3<br>+<br>+@ Pre-indexed<br>+@ CHECK: ldr  r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xb0,0xe7]<br>+@ CHECK: ldrb  r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xf0,0xe7]<br>+        ldr  r1, [r0, r2, lsr #3]!<br>+        ldrb  r1, [r0, r2, lsr #3]!<br>+<br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits<br></div></blockquote></div><br></div></body></html>