OSDN Git Service

Add alloca instruction to Subzero bitcode reader.
authorKarl Schimpf <kschimpf@google.com>
Tue, 9 Sep 2014 18:40:09 +0000 (11:40 -0700)
committerKarl Schimpf <kschimpf@google.com>
Tue, 9 Sep 2014 18:40:09 +0000 (11:40 -0700)
BUG= https://code.google.com/p/nativeclient/issues/detail?id=3894
R=jvoung@chromium.org, stichnot@chromium.org

Review URL: https://codereview.chromium.org/545623005

src/PNaClTranslator.cpp
tests_lit/reader_tests/alloca.ll [new file with mode: 0644]

index 5bfa33b..bde906a 100644 (file)
@@ -845,6 +845,8 @@ private:
   // True if the last processed instruction was a terminating
   // instruction.
   bool InstIsTerminating;
+  // Upper limit of alignment power allowed by LLVM
+  static const uint64_t AlignPowerLimit = 29;
 
   virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
 
@@ -1515,6 +1517,34 @@ void FunctionParser::ProcessRecord() {
     InstIsTerminating = true;
     break;
   }
+  case naclbitc::FUNC_CODE_INST_ALLOCA: {
+    // ALLOCA: [Size, align]
+    if (!isValidRecordSize(2, "function block alloca"))
+      return;
+    Ice::Operand *ByteCount = getRelativeOperand(Values[0]);
+    if (ByteCount->getType() != Ice::IceType_i32) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Alloca on non-i32 value. Found: " << ByteCount;
+      Error(StrBuf.str());
+      return;
+    }
+    uint64_t AlignPower = Values[1];
+    unsigned Alignment = 1;
+    if (AlignPower <= AlignPowerLimit) {
+      Alignment = (1 << static_cast<unsigned>(AlignPower)) >> 1;
+    } else {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Alloca on alignment greater than 2**" << AlignPowerLimit
+             << ". Found: 2**" << AlignPower;
+      Error(StrBuf.str());
+      // TODO(kschimpf) Remove error recovery once implementation complete.
+    }
+    Ice::Variable *Dest = NextInstVar(Context->getIcePointerType());
+    Inst = Ice::InstAlloca::create(Func, ByteCount, Alignment, Dest);
+    break;
+  }
   default:
     // Generate error message!
     BlockParserBaseClass::ProcessRecord();
diff --git a/tests_lit/reader_tests/alloca.ll b/tests_lit/reader_tests/alloca.ll
new file mode 100644 (file)
index 0000000..9ebb7c5
--- /dev/null
@@ -0,0 +1,150 @@
+; Test if we can read alloca instructions.
+
+; RUN: llvm-as < %s | pnacl-freeze \
+; RUN:              | %llvm2ice -notranslate -verbose=inst -build-on-read \
+; RUN:                -allow-pnacl-reader-error-recovery \
+; RUN:              | FileCheck %s
+
+; Show examples where size is defined by a constant.
+
+define i32 @AllocaA0Size1() {
+  %array = alloca i8, i32 1
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__0 = alloca i8, i32 1
+; CHECK-NEXT:   ret i32 %__0
+}
+
+define i32 @AllocaA0Size2() {
+  %array = alloca i8, i32 2
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__0 = alloca i8, i32 2
+; CHECK-NEXT:   ret i32 %__0
+}
+
+define i32 @AllocaA0Size3() {
+  %array = alloca i8, i32 3
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__0 = alloca i8, i32 3
+; CHECK-NEXT:   ret i32 %__0
+}
+
+define i32 @AllocaA0Size4() {
+  %array = alloca i8, i32 4
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__0 = alloca i8, i32 4
+; CHECK-NEXT:   ret i32 %__0
+}
+
+define i32 @AllocaA1Size4(i32 %n) {
+  %array = alloca i8, i32 4, align 1
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 4, align 1
+; CHECK-NEXT:   ret i32 %__1
+}
+
+define i32 @AllocaA2Size4(i32 %n) {
+  %array = alloca i8, i32 4, align 2
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 4, align 2
+; CHECK-NEXT:   ret i32 %__1
+}
+
+define i32 @AllocaA8Size4(i32 %n) {
+  %array = alloca i8, i32 4, align 8
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 4, align 8
+; CHECK-NEXT:   ret i32 %__1
+}
+
+define i32 @Alloca16Size4(i32 %n) {
+  %array = alloca i8, i32 4, align 16
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK: __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 4, align 16
+; CHECK-NEXT:   ret i32 %__1
+}
+
+; Show examples where size is not known at compile time.
+
+define i32 @AllocaVarsizeA0(i32 %n) {
+  %array = alloca i8, i32 %n
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK: __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 %__0
+; CHECK-NEXT:   ret i32 %__1
+}
+
+define i32 @AllocaVarsizeA1(i32 %n) {
+  %array = alloca i8, i32 %n, align 1
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 %__0, align 1
+; CHECK-NEXT:   ret i32 %__1
+}
+
+define i32 @AllocaVarsizeA2(i32 %n) {
+  %array = alloca i8, i32 %n, align 2
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 %__0, align 2
+; CHECK-NEXT:   ret i32 %__1
+}
+
+define i32 @AllocaVarsizeA4(i32 %n) {
+  %array = alloca i8, i32 %n, align 4
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 %__0, align 4
+; CHECK-NEXT:   ret i32 %__1
+}
+
+define i32 @AllocaVarsizeA8(i32 %n) {
+  %array = alloca i8, i32 %n, align 8
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 %__0, align 8
+; CHECK-NEXT:   ret i32 %__1
+}
+
+define i32 @AllocaVarsizeA16(i32 %n) {
+  %array = alloca i8, i32 %n, align 16
+  %addr = ptrtoint i8* %array to i32
+  ret i32 %addr
+
+; CHECK:      __0:
+; CHECK-NEXT:   %__1 = alloca i8, i32 %__0, align 16
+; CHECK-NEXT:   ret i32 %__1
+}