#include "llvm/ADT/SmallString.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
}
bool runOnMachineFunction(MachineFunction &MF) override {
- TII = static_cast<const WebAssemblyInstrInfo *>(
- MF.getSubtarget().getInstrInfo());
+ TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
return AsmPrinter::runOnMachineFunction(MF);
}
// AsmPrinter Implementation.
//===------------------------------------------------------------------===//
+ void EmitConstantPool() override;
+ void EmitFunctionEntryLabel() override;
+ void EmitFunctionBodyStart() override;
+ void EmitFunctionBodyEnd() override;
+
void EmitInstruction(const MachineInstr *MI) override;
};
static SmallString<32> Name(const WebAssemblyInstrInfo *TII,
const MachineInstr *MI) {
std::string N(StringRef(TII->getName(MI->getOpcode())).lower());
- std::string::size_type End = N.find('_');
+ std::string::size_type End = N.rfind('_');
End = std::string::npos == End ? N.length() : End;
return SmallString<32>(&N[0], &N[End]);
}
+static std::string toSymbol(StringRef S) { return ("$" + S).str(); }
+
+static const char *toType(const Type *Ty) {
+ switch (Ty->getTypeID()) {
+ default: break;
+ case Type::FloatTyID: return "f32";
+ case Type::DoubleTyID: return "f64";
+ case Type::IntegerTyID:
+ switch (Ty->getIntegerBitWidth()) {
+ case 32: return "i32";
+ case 64: return "i64";
+ default: break;
+ }
+ }
+ DEBUG(dbgs() << "Invalid type "; Ty->print(dbgs()); dbgs() << '\n');
+ llvm_unreachable("invalid type");
+ return "<invalid>";
+}
+
+void WebAssemblyAsmPrinter::EmitConstantPool() {
+ assert(MF->getConstantPool()->getConstants().empty() &&
+ "WebAssembly disables constant pools");
+}
+
+void WebAssemblyAsmPrinter::EmitFunctionEntryLabel() {
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+
+ CurrentFnSym->redefineIfPossible();
+
+ // The function label could have already been emitted if two symbols end up
+ // conflicting due to asm renaming. Detect this and emit an error.
+ if (CurrentFnSym->isVariable())
+ report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
+ "' is a protected alias");
+ if (CurrentFnSym->isDefined())
+ report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
+ "' label emitted multiple times to assembly file");
+
+ OS << "(func " << toSymbol(CurrentFnSym->getName());
+ OutStreamer->EmitRawText(OS.str());
+}
+
+void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ const Function *F = MF->getFunction();
+ for (const Argument &A : F->args())
+ OS << " (param " << toType(A.getType()) << ')';
+ const Type *Rt = F->getReturnType();
+ if (!Rt->isVoidTy())
+ OS << " (result " << toType(Rt) << ')';
+ OS << '\n';
+ OutStreamer->EmitRawText(OS.str());
+}
+
+void WebAssemblyAsmPrinter::EmitFunctionBodyEnd() {
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ OS << ") ;; end func " << toSymbol(CurrentFnSym->getName()) << '\n';
+ OutStreamer->EmitRawText(OS.str());
+}
+
void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
+ DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
SmallString<128> Str;
raw_svector_ostream OS(Str);
assert(NumDefs <= 1 &&
"Instructions with multiple result values not implemented");
+ OS << '\t';
+
if (NumDefs != 0) {
const MachineOperand &MO = MI->getOperand(0);
unsigned Reg = MO.getReg();
assert(Written < BufBytes);
OS << ' ' << buf;
} break;
+ case MachineOperand::MO_GlobalAddress: {
+ OS << ' ' << toSymbol(MO.getGlobal()->getName());
+ } break;
}
OS << ')';