Add alloca instruction to Subzero bitcode reader.
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
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index 5bfa33b..bde906a 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -845,6 +845,8 @@
// 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 @@
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
index 0000000..9ebb7c5
--- /dev/null
+++ b/tests_lit/reader_tests/alloca.ll
@@ -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
+}