Add Om1 lowering with no optimizations.
This adds infrastructure for low-level x86-32 instructions, and the target lowering patterns.
Practically no optimizations are performed. Optimizations to be introduced later include liveness analysis, dead-code elimination, global linear-scan register allocation, linear-scan based stack slot coalescing, and compare/branch fusing. One optimization that is present is simple coalescing of stack slots for variables that are only live within a single basic block.
There are also some fairly comprehensive cross tests. This testing infrastructure translates bitcode using both Subzero and llc, and a testing harness calls both versions with a variety of "interesting" inputs and compares the results. Specifically, Arithmetic, Icmp, Fcmp, and Cast instructions are tested this way, across all PNaCl primitive types.
BUG=
R=jvoung@chromium.org
Review URL: https://codereview.chromium.org/265703002
diff --git a/src/IceCfg.h b/src/IceCfg.h
index 05e1e3b..5f3bfd3 100644
--- a/src/IceCfg.h
+++ b/src/IceCfg.h
@@ -58,7 +58,7 @@
const NodeList &getNodes() const { return Nodes; }
// Manage instruction numbering.
- int newInstNumber() { return NextInstNumber++; }
+ int32_t newInstNumber() { return NextInstNumber++; }
// Manage Variables.
Variable *makeVariable(Type Ty, const CfgNode *Node,
@@ -70,16 +70,28 @@
void addArg(Variable *Arg);
const VarList &getArgs() const { return Args; }
+ // Miscellaneous accessors.
+ TargetLowering *getTarget() const { return Target.get(); }
+ bool hasComputedFrame() const;
+
+ // Passes over the CFG.
+ void translate();
// After the CFG is fully constructed, iterate over the nodes and
// compute the predecessor edges, in the form of
// CfgNode::InEdges[].
void computePredecessors();
+ void placePhiLoads();
+ void placePhiStores();
+ void deletePhis();
+ void genCode();
+ void genFrame();
// Manage the CurrentNode field, which is used for validating the
// Variable::DefNode field during dumping/emitting.
void setCurrentNode(const CfgNode *Node) { CurrentNode = Node; }
const CfgNode *getCurrentNode() const { return CurrentNode; }
+ void emit();
void dump();
// Allocate data of type T using the per-Cfg allocator.
@@ -124,9 +136,10 @@
IceString ErrorMessage;
CfgNode *Entry; // entry basic block
NodeList Nodes; // linearized node list; Entry should be first
- int NextInstNumber;
+ int32_t NextInstNumber;
VarList Variables;
VarList Args; // subset of Variables, in argument order
+ llvm::OwningPtr<TargetLowering> Target;
// CurrentNode is maintained during dumping/emitting just for
// validating Variable::DefNode. Normally, a traversal over