Commit 8f07aa88 by Karl Schimpf

Add forward instruction declaration to Subzero bitcode reader.

parent 5e06f9f4
...@@ -814,6 +814,7 @@ public: ...@@ -814,6 +814,7 @@ public:
FcnId(Context->getNextFunctionBlockValueID()), FcnId(Context->getNextFunctionBlockValueID()),
LLVMFunc(cast<Function>(Context->getGlobalValueByID(FcnId))), LLVMFunc(cast<Function>(Context->getGlobalValueByID(FcnId))),
CachedNumGlobalValueIDs(Context->getNumGlobalValueIDs()), CachedNumGlobalValueIDs(Context->getNumGlobalValueIDs()),
NextLocalInstIndex(Context->getNumGlobalValueIDs()),
InstIsTerminating(false) { InstIsTerminating(false) {
Func->setFunctionName(LLVMFunc->getName()); Func->setFunctionName(LLVMFunc->getName());
Func->setReturnType(Context->convertToIceType(LLVMFunc->getReturnType())); Func->setReturnType(Context->convertToIceType(LLVMFunc->getReturnType()));
...@@ -830,7 +831,9 @@ public: ...@@ -830,7 +831,9 @@ public:
~FunctionParser() LLVM_OVERRIDE; ~FunctionParser() LLVM_OVERRIDE;
// Set the next constant ID to the given constant C. // Set the next constant ID to the given constant C.
void setNextConstantID(Ice::Constant *C) { LocalOperands.push_back(C); } void setNextConstantID(Ice::Constant *C) {
setOperand(NextLocalInstIndex++, C);
}
private: private:
// Timer for reading function bitcode and converting to ICE. // Timer for reading function bitcode and converting to ICE.
...@@ -845,11 +848,14 @@ private: ...@@ -845,11 +848,14 @@ private:
unsigned FcnId; unsigned FcnId;
// The corresponding LLVM function. // The corresponding LLVM function.
Function *LLVMFunc; Function *LLVMFunc;
// Holds the dividing point between local and global absolute value indices.
uint32_t CachedNumGlobalValueIDs;
// Holds operands local to the function block, based on indices // Holds operands local to the function block, based on indices
// defined in the bitcode file. // defined in the bitcode file.
std::vector<Ice::Operand *> LocalOperands; std::vector<Ice::Operand *> LocalOperands;
// Holds the dividing point between local and global absolute value indices. // Holds the index within LocalOperands corresponding to the next
uint32_t CachedNumGlobalValueIDs; // instruction that generates a value.
uint32_t NextLocalInstIndex;
// True if the last processed instruction was a terminating // True if the last processed instruction was a terminating
// instruction. // instruction.
bool InstIsTerminating; bool InstIsTerminating;
...@@ -910,15 +916,42 @@ private: ...@@ -910,15 +916,42 @@ private:
return getBasicBlock(Index); return getBasicBlock(Index);
} }
// Generates the next available local variable using the given type. // Generate an instruction variable with type Ty.
Ice::Variable *getNextInstVar(Ice::Type Ty) { Ice::Variable *createInstVar(Ice::Type Ty) {
if (Ty == Ice::IceType_void) { if (Ty == Ice::IceType_void) {
Error("Can't define instruction value using type void"); Error("Can't define instruction value using type void");
// Recover since we can't throw an exception. // Recover since we can't throw an exception.
Ty = Ice::IceType_i32; Ty = Ice::IceType_i32;
} }
Ice::Variable *Var = Func->makeVariable(Ty, CurrentNode); return Func->makeVariable(Ty, CurrentNode);
LocalOperands.push_back(Var); }
// Generates the next available local variable using the given type.
Ice::Variable *getNextInstVar(Ice::Type Ty) {
assert(NextLocalInstIndex >= CachedNumGlobalValueIDs);
// Before creating one, see if a forwardtyperef has already defined it.
uint32_t LocalIndex = NextLocalInstIndex - CachedNumGlobalValueIDs;
if (LocalIndex < LocalOperands.size()) {
Ice::Operand *Op = LocalOperands[LocalIndex];
if (Op != NULL) {
if (Ice::Variable *Var = dyn_cast<Ice::Variable>(Op)) {
if (Var->getType() == Ty) {
++NextLocalInstIndex;
return Var;
}
}
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Illegal forward referenced instruction ("
<< NextLocalInstIndex << "): " << *Op;
Error(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete.
++NextLocalInstIndex;
return createInstVar(Ty);
}
}
Ice::Variable *Var = createInstVar(Ty);
setOperand(NextLocalInstIndex++, Var);
return Var; return Var;
} }
...@@ -947,12 +980,54 @@ private: ...@@ -947,12 +980,54 @@ private:
if (LocalIndex >= LocalOperands.size()) { if (LocalIndex >= LocalOperands.size()) {
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
StrBuf << "Value index " << Index << " out of range. Must be less than " StrBuf << "Value index " << Index << " not defined!";
<< (LocalOperands.size() + CachedNumGlobalValueIDs); Error(StrBuf.str());
report_fatal_error("Unable to continue");
}
Ice::Operand *Op = LocalOperands[LocalIndex];
if (Op == NULL) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Value index " << Index << " not defined!";
Error(StrBuf.str()); Error(StrBuf.str());
report_fatal_error("Unable to continue"); report_fatal_error("Unable to continue");
} }
return LocalOperands[LocalIndex]; return Op;
}
// Sets element Index (in the local operands list) to Op.
void setOperand(uint32_t Index, Ice::Operand *Op) {
assert(Op);
// Check if simple push works.
uint32_t LocalIndex = Index - CachedNumGlobalValueIDs;
if (LocalIndex == LocalOperands.size()) {
LocalOperands.push_back(Op);
return;
}
// Must be forward reference, expand vector to accommodate.
if (LocalIndex >= LocalOperands.size())
LocalOperands.resize(LocalIndex+1);
// If element not defined, set it.
Ice::Operand *OldOp = LocalOperands[LocalIndex];
if (OldOp == NULL) {
LocalOperands[LocalIndex] = Op;
return;
}
// See if forward reference matches.
if (OldOp == Op)
return;
// Error has occurred.
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Multiple definitions for index " << Index
<< ": " << *Op << " and " << *OldOp;
Error(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete.
LocalOperands[LocalIndex] = Op;
} }
// Returns the relative operand (wrt to BaseIndex) referenced by // Returns the relative operand (wrt to BaseIndex) referenced by
...@@ -963,7 +1038,7 @@ private: ...@@ -963,7 +1038,7 @@ private:
// Returns the absolute index of the next value generating instruction. // Returns the absolute index of the next value generating instruction.
uint32_t getNextInstIndex() const { uint32_t getNextInstIndex() const {
return CachedNumGlobalValueIDs + LocalOperands.size(); return NextLocalInstIndex;
} }
// Generates type error message for binary operator Op // Generates type error message for binary operator Op
...@@ -1702,10 +1777,17 @@ void FunctionParser::ProcessRecord() { ...@@ -1702,10 +1777,17 @@ void FunctionParser::ProcessRecord() {
Ice::InstStore::create(Func, Value, Address, Alignment)); Ice::InstStore::create(Func, Value, Address, Alignment));
break; break;
} }
case naclbitc::FUNC_CODE_INST_FORWARDTYPEREF: {
// FORWARDTYPEREF: [opval, ty]
if (!isValidRecordSize(2, "function block forward type ref"))
return;
setOperand(Values[0], createInstVar(
Context->convertToIceType(Context->getTypeByID(Values[1]))));
break;
}
case naclbitc::FUNC_CODE_INST_SWITCH: case naclbitc::FUNC_CODE_INST_SWITCH:
case naclbitc::FUNC_CODE_INST_CALL: case naclbitc::FUNC_CODE_INST_CALL:
case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: case naclbitc::FUNC_CODE_INST_CALL_INDIRECT:
case naclbitc::FUNC_CODE_INST_FORWARDTYPEREF:
default: default:
// Generate error message! // Generate error message!
BlockParserBaseClass::ProcessRecord(); BlockParserBaseClass::ProcessRecord();
......
...@@ -48,7 +48,8 @@ config.substitutions.append(('%llvm2ice', llvm2icetool)) ...@@ -48,7 +48,8 @@ config.substitutions.append(('%llvm2ice', llvm2icetool))
config.substitutions.append(('%szdiff', os.path.join(pydir, 'szdiff.py'))) config.substitutions.append(('%szdiff', os.path.join(pydir, 'szdiff.py')))
llvmbintools = [r"\bFileCheck\b", r"\bllvm-as\b", r"\bllvm-mc\b", llvmbintools = [r"\bFileCheck\b", r"\bllvm-as\b", r"\bllvm-mc\b",
r"\bllvm-objdump\b", r"\bnot\b", r"\bpnacl-freeze\b"] r"\bllvm-objdump\b", r"\bnot\b", r"\bpnacl-freeze\b",
r"\bpnacl-bcdis\b"]
for tool in llvmbintools: for tool in llvmbintools:
# The re.sub() line is adapted from one of LLVM's lit.cfg files. # The re.sub() line is adapted from one of LLVM's lit.cfg files.
......
; Test use forward type references in function blocks.
; RUN: llvm-as < %s | pnacl-freeze -allow-local-symbol-tables \
; RUN: | %llvm2ice -notranslate -verbose=inst -build-on-read \
; RUN: -allow-pnacl-reader-error-recovery \
; RUN: -allow-local-symbol-tables \
; RUN: | FileCheck %s
; RUN: llvm-as < %s | pnacl-freeze | pnacl-bcdis -no-records \
; RUN: | FileCheck --check-prefix=DUMP %s
define void @LoopCarriedDep() {
b0:
%v0 = add i32 1, 2
br label %b1
b1:
%v1 = phi i32 [%v0, %b0], [%v2, %b1]
%v2 = add i32 %v1, 1
br label %b1
}
; CHECK: define void @LoopCarriedDep() {
; CHECK-NEXT: b0:
; CHECK-NEXT: %v0 = add i32 1, 2
; CHECK-NEXT: br label %b1
; CHECK-NEXT: b1:
; CHECK-NEXT: %v1 = phi i32 [ %v0, %b0 ], [ %v2, %b1 ]
; CHECK-NEXT: %v2 = add i32 %v1, 1
; CHECK-NEXT: br label %b1
; CHECK-NEXT: }
; Snippet of bitcode objdump with forward type reference (see "declare").
; DUMP: function void @f0() { // BlockID = 12
; DUMP-NEXT: blocks 2;
; DUMP-NEXT: constants { // BlockID = 11
; DUMP-NEXT: i32: <@a0>
; DUMP-NEXT: %c0 = i32 1; <@a1>
; DUMP-NEXT: %c1 = i32 2; <@a1>
; DUMP-NEXT: }
; DUMP-NEXT: %b0:
; DUMP-NEXT: %v0 = add i32 %c0, %c1; <@a1>
; DUMP-NEXT: br label %b1;
; DUMP-NEXT: %b1:
; DUMP-NEXT: declare i32 %v2; <@a6>
; DUMP-NEXT: %v1 = phi i32 [%v0, %b0], [%v2, %b1];
; DUMP-NEXT: %v2 = add i32 %v1, %c0; <@a1>
; DUMP-NEXT: br label %b1;
; DUMP-NEXT: }
define void @BackBranch(i32 %p0) {
b0:
br label %b4
b1:
%v0 = add i32 %p0, %v3
br label %b6
b2:
%v1 = add i32 %p0, %v4
br label %b6
b3:
%v2 = add i32 %p0, %v3 ; No forward declare, already done!
br label %b6
b4:
%v3 = add i32 %p0, %p0
br i1 1, label %b1, label %b5
b5:
%v4 = add i32 %v3, %p0
br i1 1, label %b2, label %b3
b6:
ret void
}
; CHECK: define void @BackBranch(i32 %p0) {
; CHECK-NEXT: b0:
; CHECK-NEXT: br label %b4
; CHECK-NEXT: b1:
; CHECK-NEXT: %v0 = add i32 %p0, %v3
; CHECK-NEXT: br label %b6
; CHECK-NEXT: b2:
; CHECK-NEXT: %v1 = add i32 %p0, %v4
; CHECK-NEXT: br label %b6
; CHECK-NEXT: b3:
; CHECK-NEXT: %v2 = add i32 %p0, %v3
; CHECK-NEXT: br label %b6
; CHECK-NEXT: b4:
; CHECK-NEXT: %v3 = add i32 %p0, %p0
; CHECK-NEXT: br i1 true, label %b1, label %b5
; CHECK-NEXT: b5:
; CHECK-NEXT: %v4 = add i32 %v3, %p0
; CHECK-NEXT: br i1 true, label %b2, label %b3
; CHECK-NEXT: b6:
; CHECK-NEXT: ret void
; CHECK-NEXT: }
; Snippet of bitcode objdump with forward type references (see "declare").
; DUMP: function void @f1(i32 %p0) { // BlockID = 12
; DUMP-NEXT: blocks 7;
; DUMP-NEXT: constants { // BlockID = 11
; DUMP-NEXT: i1: <@a0>
; DUMP-NEXT: %c0 = i1 1; <@a1>
; DUMP-NEXT: }
; DUMP-NEXT: %b0:
; DUMP-NEXT: br label %b4;
; DUMP-NEXT: %b1:
; DUMP-NEXT: declare i32 %v3; <@a6>
; DUMP-NEXT: %v0 = add i32 %p0, %v3; <@a1>
; DUMP-NEXT: br label %b6;
; DUMP-NEXT: %b2:
; DUMP-NEXT: declare i32 %v4; <@a6>
; DUMP-NEXT: %v1 = add i32 %p0, %v4; <@a1>
; DUMP-NEXT: br label %b6;
; DUMP-NEXT: %b3:
; DUMP-NEXT: %v2 = add i32 %p0, %v3; <@a1>
; DUMP-NEXT: br label %b6;
; DUMP-NEXT: %b4:
; DUMP-NEXT: %v3 = add i32 %p0, %p0; <@a1>
; DUMP-NEXT: br i1 %c0, label %b1, label %b5;
; DUMP-NEXT: %b5:
; DUMP-NEXT: %v4 = add i32 %v3, %p0; <@a1>
; DUMP-NEXT: br i1 %c0, label %b2, label %b3;
; DUMP-NEXT: %b6:
; DUMP-NEXT: ret void; <@a3>
; DUMP-NEXT: }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment