GlobalISel: implement alloca instruction

llvm-svn: 276433
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index e017b49..82cec25 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -15,6 +15,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/IR/Constant.h"
 #include "llvm/IR/Function.h"
@@ -43,7 +44,7 @@
     assert(Val.getType()->isSized() &&
            "Don't know how to create an empty vreg");
     assert(!Val.getType()->isAggregateType() && "Not yet implemented");
-    unsigned Size = Val.getType()->getPrimitiveSizeInBits();
+    unsigned Size = DL->getTypeSizeInBits(Val.getType());
     unsigned VReg = MRI->createGenericVirtualRegister(Size);
     ValReg = VReg;
     assert(!isa<Constant>(Val) && "Not yet implemented");
@@ -99,6 +100,23 @@
   return true;
 }
 
+bool IRTranslator::translateStaticAlloca(const AllocaInst &AI) {
+  assert(AI.isStaticAlloca() && "only handle static allocas now");
+  MachineFunction &MF = MIRBuilder.getMF();
+  unsigned ElementSize = DL->getTypeStoreSize(AI.getAllocatedType());
+  unsigned Size =
+      ElementSize * cast<ConstantInt>(AI.getArraySize())->getZExtValue();
+
+  unsigned Alignment = AI.getAlignment();
+  if (!Alignment)
+    Alignment = DL->getABITypeAlignment(AI.getAllocatedType());
+
+  unsigned Res = getOrCreateVReg(AI);
+  int FI = MF.getFrameInfo()->CreateStackObject(Size, Alignment, false, &AI);
+  MIRBuilder.buildFrameIndex(LLT::pointer(0), Res, FI);
+  return true;
+}
+
 bool IRTranslator::translate(const Instruction &Inst) {
   MIRBuilder.setDebugLoc(Inst.getDebugLoc());
   switch(Inst.getOpcode()) {
@@ -107,17 +125,22 @@
     return translateBinaryOp(TargetOpcode::G_ADD, Inst);
   case Instruction::Sub:
     return translateBinaryOp(TargetOpcode::G_SUB, Inst);
+
   // Bitwise operations.
   case Instruction::And:
     return translateBinaryOp(TargetOpcode::G_AND, Inst);
   case Instruction::Or:
     return translateBinaryOp(TargetOpcode::G_OR, Inst);
+
   // Branch operations.
   case Instruction::Br:
     return translateBr(Inst);
   case Instruction::Ret:
     return translateReturn(Inst);
 
+  case Instruction::Alloca:
+    return translateStaticAlloca(cast<AllocaInst>(Inst));
+
   default:
     llvm_unreachable("Opcode not supported");
   }
@@ -138,6 +161,8 @@
   CLI = MF.getSubtarget().getCallLowering();
   MIRBuilder.setMF(MF);
   MRI = &MF.getRegInfo();
+  DL = &F.getParent()->getDataLayout();
+
   // Setup the arguments.
   MachineBasicBlock &MBB = getOrCreateBB(F.front());
   MIRBuilder.setMBB(MBB);
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 382652f..220965c 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -102,3 +102,11 @@
   MachineInstrBuilder(getMF(), NewMI).addMBB(&BB);
   return NewMI;
 }
+
+MachineInstr *MachineIRBuilder::buildFrameIndex(LLT Ty, unsigned Res, int Idx) {
+  MachineInstr *NewMI = buildInstr(TargetOpcode::G_FRAME_INDEX, Ty);
+  auto MIB = MachineInstrBuilder(getMF(), NewMI);
+  MIB.addReg(Res, RegState::Define);
+  MIB.addImm(Idx);
+  return NewMI;
+}
diff --git a/llvm/lib/CodeGen/LowLevelType.cpp b/llvm/lib/CodeGen/LowLevelType.cpp
index 0f69622..c81535c 100644
--- a/llvm/lib/CodeGen/LowLevelType.cpp
+++ b/llvm/lib/CodeGen/LowLevelType.cpp
@@ -19,26 +19,32 @@
 
 LLT::LLT(const Type &Ty) {
   if (auto VTy = dyn_cast<VectorType>(&Ty)) {
-    ScalarSize = VTy->getElementType()->getPrimitiveSizeInBits();
+    SizeOrAddrSpace = VTy->getElementType()->getPrimitiveSizeInBits();
     NumElements = VTy->getNumElements();
     Kind = NumElements == 1 ? Scalar : Vector;
+  } else if (auto PTy = dyn_cast<PointerType>(&Ty)) {
+    Kind = Pointer;
+    SizeOrAddrSpace = PTy->getAddressSpace();
+    NumElements = 1;
   } else if (Ty.isSized()) {
     // Aggregates are no different from real scalars as far as GlobalISel is
     // concerned.
     Kind = Scalar;
-    ScalarSize = Ty.getPrimitiveSizeInBits();
+    SizeOrAddrSpace = Ty.getPrimitiveSizeInBits();
     NumElements = 1;
   } else {
     Kind = Unsized;
-    ScalarSize = NumElements = 0;
+    SizeOrAddrSpace = NumElements = 0;
   }
 }
 
 void LLT::print(raw_ostream &OS) const {
   if (isVector())
-    OS << "<" << NumElements << " x s" << ScalarSize << ">";
+    OS << "<" << NumElements << " x s" << SizeOrAddrSpace << ">";
+  else if (isPointer())
+    OS << "p" << getAddressSpace();
   else if (isSized())
-    OS << "s" << ScalarSize;
+    OS << "s" << getScalarSizeInBits();
   else if (isValid())
     OS << "unsized";
   else
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index c9b4135f..503b52d 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -174,14 +174,18 @@
 }
 
 static Cursor maybeLexIntegerOrScalarType(Cursor C, MIToken &Token) {
-  if ((C.peek() != 'i' && C.peek() != 's') || !isdigit(C.peek(1)))
+  if ((C.peek() != 'i' && C.peek() != 's' && C.peek() != 'p') ||
+      !isdigit(C.peek(1)))
     return None;
   char Kind = C.peek();
   auto Range = C;
-  C.advance(); // Skip 'i'
+  C.advance(); // Skip 'i', 's', or 'p'
   while (isdigit(C.peek()))
     C.advance();
-  Token.reset(Kind == 'i' ? MIToken::IntegerType : MIToken::ScalarType,
+
+  Token.reset(Kind == 'i'
+                  ? MIToken::IntegerType
+                  : (Kind == 's' ? MIToken::ScalarType : MIToken::PointerType),
               Range.upto(C));
   return C;
 }
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index a5a95f8..ea155c3 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -102,6 +102,7 @@
     NamedRegister,
     MachineBasicBlockLabel,
     MachineBasicBlock,
+    PointerType,
     ScalarType,
     StackObject,
     FixedStackObject,
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index e4ca9ae..695c58d 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1030,7 +1030,7 @@
                                  bool MustBeSized) {
   if (Token.is(MIToken::Identifier) && Token.stringValue() == "unsized") {
     if (MustBeSized)
-      return error(Loc, "expected sN or <N x sM> for sized GlobalISel type");
+      return error(Loc, "expected pN, sN or <N x sM> for sized GlobalISel type");
     lex();
     Ty = LLT::unsized();
     return false;
@@ -1038,11 +1038,17 @@
     Ty = LLT::scalar(APSInt(Token.range().drop_front()).getZExtValue());
     lex();
     return false;
+  } else if (Token.is(MIToken::PointerType)) {
+    Ty = LLT::pointer(APSInt(Token.range().drop_front()).getZExtValue());
+    lex();
+    return false;
   }
 
   // Now we're looking for a vector.
   if (Token.isNot(MIToken::less))
-    return error(Loc, "expected unsized, sN or <N x sM> for GlobalISel type");
+    return error(Loc,
+                 "expected unsized, pN, sN or <N x sM> for GlobalISel type");
+
   lex();
 
   if (Token.isNot(MIToken::IntegerLiteral))