summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
diff options
context:
space:
mode:
authorJF Bastien <jfb@google.com>2015-10-16 00:53:49 +0000
committerJF Bastien <jfb@google.com>2015-10-16 00:53:49 +0000
commit1d20a5e9e8061848c33207da5d02c6fbd706ffc1 (patch)
tree0e1bfd186c16b0b60563390a311ebdd079349fe4 /llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
parentad5e0cefa15d81cf3688a65b55d7e26d91512150 (diff)
downloadbcm5719-llvm-1d20a5e9e8061848c33207da5d02c6fbd706ffc1.tar.gz
bcm5719-llvm-1d20a5e9e8061848c33207da5d02c6fbd706ffc1.zip
WebAssembly: update syntax
Summary: Follow the same syntax as for the spec repo. Both have evolved slightly independently and need to converge again. This, along with wasmate changes, allows me to do the following: echo "int add(int a, int b) { return a + b; }" > add.c ./out/bin/clang -O2 -S --target=wasm32-unknown-unknown add.c -o add.wack ./experimental/prototype-wasmate/wasmate.py add.wack > add.wast ./sexpr-wasm-prototype/out/sexpr-wasm add.wast -o add.wasm ./sexpr-wasm-prototype/third_party/v8-native-prototype/v8/v8/out/Release/d8 -e "print(WASM.instantiateModule(readbuffer('add.wasm'), {print:print}).add(42, 1337));" As you'd expect, the d8 shell prints out the right value. Reviewers: sunfish Subscribers: jfb, llvm-commits, dschuff Differential Revision: http://reviews.llvm.org/D13712 llvm-svn: 250480
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp90
1 files changed, 59 insertions, 31 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index f62cec9f594..5c8fe570847 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -42,11 +42,12 @@ namespace {
class WebAssemblyAsmPrinter final : public AsmPrinter {
const WebAssemblyInstrInfo *TII;
+ const MachineRegisterInfo *MRI;
unsigned NumArgs;
public:
WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
- : AsmPrinter(TM, std::move(Streamer)), TII(nullptr) {}
+ : AsmPrinter(TM, std::move(Streamer)), TII(nullptr), MRI(nullptr) {}
private:
const char *getPassName() const override {
@@ -64,6 +65,7 @@ private:
bool runOnMachineFunction(MachineFunction &MF) override {
const auto &Subtarget = MF.getSubtarget<WebAssemblySubtarget>();
TII = Subtarget.getInstrInfo();
+ MRI = &MF.getRegInfo();
NumArgs = MF.getInfo<WebAssemblyFunctionInfo>()->getNumArguments();
return AsmPrinter::runOnMachineFunction(MF);
}
@@ -78,10 +80,11 @@ private:
void EmitInstruction(const MachineInstr *MI) override;
+ std::string getRegTypeName(unsigned RegNo) const;
static std::string toString(const APFloat &APF);
const char *toString(Type *Ty) const;
- std::string regToString(unsigned RegNo);
- std::string argToString(unsigned ArgNo);
+ std::string regToString(const MachineOperand &MO);
+ std::string argToString(const MachineOperand &MO);
};
} // end anonymous namespace
@@ -90,19 +93,33 @@ private:
// Helpers.
//===----------------------------------------------------------------------===//
-// Untyped, lower-case version of the opcode's name matching the names
-// WebAssembly opcodes are expected to have. The tablegen names are uppercase
-// and suffixed with their type (after an underscore).
-static SmallString<32> OpcodeName(const WebAssemblyInstrInfo *TII,
- const MachineInstr *MI) {
+// Operand type (if any), followed by the lower-case version of the opcode's
+// name matching the names WebAssembly opcodes are expected to have. The
+// tablegen names are uppercase and suffixed with their type (after an
+// underscore).
+static std::string OpcodeName(const WebAssemblyInstrInfo *TII,
+ const MachineInstr *MI) {
std::string N(StringRef(TII->getName(MI->getOpcode())).lower());
- std::string::size_type End = N.rfind('_');
- End = std::string::npos == End ? N.length() : End;
- return SmallString<32>(&N[0], &N[End]);
+ std::string::size_type Len = N.length();
+ std::string::size_type Under = N.rfind('_');
+ bool HasType = std::string::npos != Under;
+ std::string::size_type NameEnd = HasType ? Under : Len;
+ std::string Name(&N[0], &N[NameEnd]);
+ return HasType ? (std::string(&N[NameEnd + 1], &N[Len]) + '.' + Name) : Name;
}
static std::string toSymbol(StringRef S) { return ("$" + S).str(); }
+std::string WebAssemblyAsmPrinter::getRegTypeName(unsigned RegNo) const {
+ const TargetRegisterClass *TRC = MRI->getRegClass(RegNo);
+ for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
+ if (TRC->hasType(T))
+ return EVT(T).getEVTString();
+ DEBUG(errs() << "Unknown type for register number: " << RegNo);
+ llvm_unreachable("Unknown register type");
+ return "?";
+}
+
std::string WebAssemblyAsmPrinter::toString(const APFloat &FP) {
static const size_t BufBytes = 128;
char buf[BufBytes];
@@ -120,19 +137,21 @@ std::string WebAssemblyAsmPrinter::toString(const APFloat &FP) {
return buf;
}
-std::string WebAssemblyAsmPrinter::regToString(unsigned RegNo) {
+std::string WebAssemblyAsmPrinter::regToString(const MachineOperand &MO) {
+ unsigned RegNo = MO.getReg();
if (TargetRegisterInfo::isPhysicalRegister(RegNo))
return WebAssemblyInstPrinter::getRegisterName(RegNo);
// WebAssembly arguments and local variables are in the same index space, and
// there are no explicit varargs, so we just add the number of arguments to
// the virtual register number to get the local variable number.
- return '@' + utostr(TargetRegisterInfo::virtReg2Index(RegNo) + NumArgs);
+ return utostr(TargetRegisterInfo::virtReg2Index(RegNo) + NumArgs);
}
-std::string WebAssemblyAsmPrinter::argToString(unsigned ArgNo) {
+std::string WebAssemblyAsmPrinter::argToString(const MachineOperand &MO) {
+ unsigned ArgNo = MO.getImm();
// Same as above, but we don't need to add NumArgs here.
- return '@' + utostr(ArgNo);
+ return utostr(ArgNo);
}
const char *WebAssemblyAsmPrinter::toString(Type *Ty) const {
@@ -189,26 +208,36 @@ void WebAssemblyAsmPrinter::EmitJumpTableInfo() {
void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
const Function *F = MF->getFunction();
Type *Rt = F->getReturnType();
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ bool First = true;
if (!Rt->isVoidTy() || !F->arg_empty()) {
- SmallString<128> Str;
- raw_svector_ostream OS(Str);
- bool First = true;
for (const Argument &A : F->args()) {
- OS << (First ? "" : "\n") << "\t"
- ".param "
- << toString(A.getType());
+ OS << (First ? "" : "\n") << "\t.param " << toString(A.getType());
First = false;
}
if (!Rt->isVoidTy()) {
- OS << (First ? "" : "\n") << "\t"
- ".result "
- << toString(Rt);
+ OS << (First ? "" : "\n") << "\t.result " << toString(Rt);
First = false;
}
- OutStreamer->EmitRawText(OS.str());
}
+ bool FirstVReg = true;
+ for (unsigned Idx = 0, IdxE = MRI->getNumVirtRegs(); Idx != IdxE; ++Idx) {
+ unsigned VReg = TargetRegisterInfo::index2VirtReg(Idx);
+ if (!MRI->use_empty(VReg)) {
+ if (FirstVReg) {
+ OS << (First ? "" : "\n") << "\t.local ";
+ First = false;
+ }
+ OS << (FirstVReg ? "" : ", ") << getRegTypeName(VReg);
+ FirstVReg = false;
+ }
+ }
+
+ if (!First)
+ OutStreamer->EmitRawText(OS.str());
AsmPrinter::EmitFunctionBodyStart();
}
@@ -225,7 +254,7 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
switch (MI->getOpcode()) {
case TargetOpcode::COPY:
- OS << regToString(MI->getOperand(1).getReg());
+ OS << "get_local " << regToString(MI->getOperand(1));
break;
case WebAssembly::GLOBAL:
// TODO: wasm64
@@ -235,7 +264,7 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case WebAssembly::ARGUMENT_I64:
case WebAssembly::ARGUMENT_F32:
case WebAssembly::ARGUMENT_F64:
- OS << argToString(MI->getOperand(1).getImm());
+ OS << "get_local " << argToString(MI->getOperand(1));
break;
case WebAssembly::Immediate_I32:
OS << "i32.const " << MI->getOperand(1).getImm();
@@ -263,7 +292,7 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
default:
llvm_unreachable("unexpected machine operand type");
case MachineOperand::MO_Register:
- OS << regToString(MO.getReg());
+ OS << "(get_local " << regToString(MO) << ')';
break;
case MachineOperand::MO_Immediate:
OS << MO.getImm();
@@ -288,9 +317,8 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (NumDefs != 0) {
SmallString<128> Str;
raw_svector_ostream OS(Str);
- OS << "\t" "set_local "
- << regToString(MI->getOperand(0).getReg()) << ", "
- "pop";
+ const MachineOperand &Operand = MI->getOperand(0);
+ OS << "\tset_local " << regToString(Operand) << ", pop";
OutStreamer->EmitRawText(OS.str());
}
}
OpenPOWER on IntegriCloud