Align function starts to target-specific bundle alignment.

BUG=none
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/515993002
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index 6fe7eb0..d699ef5 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -314,6 +314,13 @@
     Str << "\t.globl\t" << MangledName << "\n";
     Str << "\t.type\t" << MangledName << ",@function\n";
   }
+  Str << "\t.p2align " << getTarget()->getBundleAlignLog2Bytes() << ",0x";
+  llvm::ArrayRef<uint8_t> Pad = getTarget()->getNonExecBundlePadding();
+  for (llvm::ArrayRef<uint8_t>::iterator I = Pad.begin(), E = Pad.end();
+       I != E; ++I) {
+    Str.write_hex(*I);
+  }
+  Str << "\n";
   for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E;
        ++I) {
     (*I)->emit(this);
diff --git a/src/IceDefs.h b/src/IceDefs.h
index d156a60..5cd1282 100644
--- a/src/IceDefs.h
+++ b/src/IceDefs.h
@@ -27,6 +27,7 @@
 #include <string>
 #include <vector>
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/STLExtras.h"
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index 6bf1424..a3410eb 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -137,6 +137,8 @@
   virtual bool hasFramePointer() const { return false; }
   virtual SizeT getFrameOrStackReg() const = 0;
   virtual size_t typeWidthInBytesOnStack(Type Ty) const = 0;
+  virtual SizeT getBundleAlignLog2Bytes() const = 0;
+  virtual llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const = 0;
   bool hasComputedFrame() const { return HasComputedFrame; }
   bool shouldDoNopInsertion() const;
   int32_t getStackAdjustment() const { return StackAdjustment; }
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index 499790e..6f8ee02 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -45,6 +45,11 @@
     // i8, and i16 are rounded up to 4 bytes.
     return (typeWidthInBytes(Ty) + 3) & ~3;
   }
+  virtual SizeT getBundleAlignLog2Bytes() const { return 5; }
+  virtual llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const {
+    static const uint8_t Padding[] = { 0xF4 };
+    return llvm::ArrayRef<uint8_t>(Padding, 1);
+  }
   virtual void emitVariable(const Variable *Var, const Cfg *Func) const;
   virtual void lowerArguments();
   virtual void addProlog(CfgNode *Node);
diff --git a/tests_lit/lit.cfg b/tests_lit/lit.cfg
index 735474e..1edf2f9 100644
--- a/tests_lit/lit.cfg
+++ b/tests_lit/lit.cfg
@@ -42,8 +42,8 @@
 config.substitutions.append(('%llvm2ice', llvm2icetool))
 config.substitutions.append(('%szdiff', os.path.join(bin_root, 'szdiff.py')))
 
-llvmbintools = [r"\bFileCheck\b", r"\bllvm-mc\b", r"\bnot\b",
-                r"\bpnacl-freeze\b"]
+llvmbintools = [r"\bFileCheck\b", r"\bllvm-mc\b", r"\bllvm-objdump\b",
+                r"\bnot\b", r"\bpnacl-freeze\b"]
 
 for tool in llvmbintools:
   # The re.sub() line is adapted from one of LLVM's lit.cfg files.
diff --git a/tests_lit/llvm2ice_tests/function_aligned.ll b/tests_lit/llvm2ice_tests/function_aligned.ll
new file mode 100644
index 0000000..fcb4699
--- /dev/null
+++ b/tests_lit/llvm2ice_tests/function_aligned.ll
@@ -0,0 +1,21 @@
+; Test that functions are aligned to the NaCl bundle alignment.
+; We could be smarter and only do this for indirect call targets
+; but typically you want to align functions anyway.
+; Also, we are currently using hlts for non-executable padding.
+
+; RUN: %llvm2ice -O2 --verbose none %s \
+; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
+; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
+
+define void @foo() {
+  ret void
+}
+; CHECK-LABEL: foo
+; CHECK-NEXT: 0: {{.*}} ret
+; CHECK-NEXT: 1: {{.*}} hlt
+
+define void @bar() {
+  ret void
+}
+; CHECK-LABEL: bar
+; CHECK-NEXT: 20: {{.*}} ret