diff options
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
4 files changed, 113 insertions, 144 deletions
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp index 092f1f11960..d2617796ca9 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp @@ -27,9 +27,6 @@ WebAssemblyMCAsmInfo::WebAssemblyMCAsmInfo(const Triple &T) { // TODO: What should MaxInstLength be? - // The s-expression format of WebAssembly uses LISP-style comments. - CommentString = ";;"; - PrivateGlobalPrefix = ""; PrivateLabelPrefix = ""; @@ -44,17 +41,10 @@ WebAssemblyMCAsmInfo::WebAssemblyMCAsmInfo(const Triple &T) { COMMDirectiveAlignmentIsInBytes = false; LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment; - HasDotTypeDotSizeDirective = false; - HasSingleParameterDotFile = false; - SupportsDebugInformation = true; // For now, WebAssembly does not support exceptions. ExceptionsType = ExceptionHandling::None; - // FIXME: modify AsmPrinter to be more flexible, and fix other virtual ISAs. - WeakDirective = "\t;; .weak\t"; - GlobalDirective = "\t;; .globl\t"; - // TODO: UseIntegratedAssembler? } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index 30d12497e43..f62cec9f594 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -22,6 +22,7 @@ #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineInstr.h" @@ -41,6 +42,7 @@ namespace { class WebAssemblyAsmPrinter final : public AsmPrinter { const WebAssemblyInstrInfo *TII; + unsigned NumArgs; public: WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) @@ -62,6 +64,7 @@ private: bool runOnMachineFunction(MachineFunction &MF) override { const auto &Subtarget = MF.getSubtarget<WebAssemblySubtarget>(); TII = Subtarget.getInstrInfo(); + NumArgs = MF.getInfo<WebAssemblyFunctionInfo>()->getNumArguments(); return AsmPrinter::runOnMachineFunction(MF); } @@ -69,18 +72,16 @@ private: // AsmPrinter Implementation. //===------------------------------------------------------------------===// - void EmitGlobalVariable(const GlobalVariable *GV) override; - void EmitJumpTableInfo() override; void EmitConstantPool() override; - void EmitFunctionEntryLabel() override; void EmitFunctionBodyStart() override; - void EmitFunctionBodyEnd() override; void EmitInstruction(const MachineInstr *MI) override; static std::string toString(const APFloat &APF); const char *toString(Type *Ty) const; + std::string regToString(unsigned RegNo); + std::string argToString(unsigned ArgNo); }; } // end anonymous namespace @@ -119,6 +120,21 @@ std::string WebAssemblyAsmPrinter::toString(const APFloat &FP) { return buf; } +std::string WebAssemblyAsmPrinter::regToString(unsigned RegNo) { + 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); +} + +std::string WebAssemblyAsmPrinter::argToString(unsigned ArgNo) { + // Same as above, but we don't need to add NumArgs here. + return '@' + utostr(ArgNo); +} + const char *WebAssemblyAsmPrinter::toString(Type *Ty) const { switch (Ty->getTypeID()) { default: @@ -161,70 +177,6 @@ const char *WebAssemblyAsmPrinter::toString(Type *Ty) const { // WebAssemblyAsmPrinter Implementation. //===----------------------------------------------------------------------===// -void WebAssemblyAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - StringRef Name = GV->getName(); - DEBUG(dbgs() << "Global " << Name << '\n'); - - if (!GV->hasInitializer()) { - DEBUG(dbgs() << " Skipping declaration.\n"); - return; - } - - // Check to see if this is a special global used by LLVM. - static const char *Ignored[] = {"llvm.used", "llvm.metadata"}; - for (const char *I : Ignored) - if (Name == I) - return; - // FIXME: Handle the following globals. - static const char *Unhandled[] = {"llvm.global_ctors", "llvm.global_dtors"}; - for (const char *U : Unhandled) - if (Name == U) - report_fatal_error("Unhandled global"); - if (Name.startswith("llvm.")) - report_fatal_error("Unknown LLVM-internal global"); - - if (GV->isThreadLocal()) - report_fatal_error("TLS isn't yet supported by WebAssembly"); - - const DataLayout &DL = getDataLayout(); - const Constant *Init = GV->getInitializer(); - if (isa<UndefValue>(Init)) - Init = Constant::getNullValue(Init->getType()); - unsigned Align = DL.getPrefTypeAlignment(Init->getType()); - - switch (GV->getLinkage()) { - case GlobalValue::InternalLinkage: - case GlobalValue::PrivateLinkage: - break; - case GlobalValue::AppendingLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::ExternalLinkage: - case GlobalValue::CommonLinkage: - report_fatal_error("Linkage types other than internal and private aren't " - "supported by WebAssembly yet"); - default: - llvm_unreachable("Unknown linkage type"); - return; - } - - OS << "(global " << toSymbol(Name) << ' ' << toString(Init->getType()) << ' '; - if (const auto *C = dyn_cast<ConstantInt>(Init)) { - assert(C->getBitWidth() <= 64 && "Printing wider types unimplemented"); - OS << C->getZExtValue(); - } else if (const auto *C = dyn_cast<ConstantFP>(Init)) { - OS << toString(C->getValueAPF()); - } else { - assert(false && "Only integer and floating-point constants are supported"); - } - OS << ") ;; align " << Align; - OutStreamer->EmitRawText(OS.str()); -} - void WebAssemblyAsmPrinter::EmitConstantPool() { assert(MF->getConstantPool()->getConstants().empty() && "WebAssembly disables constant pools"); @@ -234,44 +186,30 @@ void WebAssemblyAsmPrinter::EmitJumpTableInfo() { // Nothing to do; jump tables are incorporated into the instruction stream. } -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(); Type *Rt = F->getReturnType(); + if (!Rt->isVoidTy() || !F->arg_empty()) { - for (const Argument &A : F->args()) - OS << " (param " << toString(A.getType()) << ')'; - if (!Rt->isVoidTy()) - OS << " (result " << toString(Rt) << ')'; + 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()); + First = false; + } + if (!Rt->isVoidTy()) { + OS << (First ? "" : "\n") << "\t" + ".result " + << toString(Rt); + First = false; + } OutStreamer->EmitRawText(OS.str()); } -} -void WebAssemblyAsmPrinter::EmitFunctionBodyEnd() { - SmallString<128> Str; - raw_svector_ostream OS(Str); - OS << ") ;; end func " << toSymbol(CurrentFnSym->getName()); - OutStreamer->EmitRawText(OS.str()); + AsmPrinter::EmitFunctionBodyStart(); } void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { @@ -285,46 +223,76 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { OS << '\t'; - if (NumDefs != 0) { - const MachineOperand &MO = MI->getOperand(0); - unsigned Reg = MO.getReg(); - OS << "(set_local @" << TargetRegisterInfo::virtReg2Index(Reg) << ' '; - } - - if (MI->getOpcode() == WebAssembly::COPY) { - OS << '@' << TargetRegisterInfo::virtReg2Index(MI->getOperand(1).getReg()); - } else { - OS << '(' << OpcodeName(TII, MI); - for (const MachineOperand &MO : MI->uses()) + switch (MI->getOpcode()) { + case TargetOpcode::COPY: + OS << regToString(MI->getOperand(1).getReg()); + break; + case WebAssembly::GLOBAL: + // TODO: wasm64 + OS << "i32.const " << toSymbol(MI->getOperand(1).getGlobal()->getName()); + break; + case WebAssembly::ARGUMENT_I32: + case WebAssembly::ARGUMENT_I64: + case WebAssembly::ARGUMENT_F32: + case WebAssembly::ARGUMENT_F64: + OS << argToString(MI->getOperand(1).getImm()); + break; + case WebAssembly::Immediate_I32: + OS << "i32.const " << MI->getOperand(1).getImm(); + break; + case WebAssembly::Immediate_I64: + OS << "i64.const " << MI->getOperand(1).getImm(); + break; + case WebAssembly::Immediate_F32: + OS << "f32.const " << toString(MI->getOperand(1).getFPImm()->getValueAPF()); + break; + case WebAssembly::Immediate_F64: + OS << "f64.const " << toString(MI->getOperand(1).getFPImm()->getValueAPF()); + break; + default: { + OS << OpcodeName(TII, MI); + bool NeedComma = false; + for (const MachineOperand &MO : MI->uses()) { + if (MO.isReg() && MO.isImplicit()) + continue; + if (NeedComma) + OS << ','; + NeedComma = true; + OS << ' '; switch (MO.getType()) { default: llvm_unreachable("unexpected machine operand type"); - case MachineOperand::MO_Register: { - if (MO.isImplicit()) - continue; - unsigned Reg = MO.getReg(); - OS << " @" << TargetRegisterInfo::virtReg2Index(Reg); - } break; - case MachineOperand::MO_Immediate: { - OS << ' ' << MO.getImm(); - } break; - case MachineOperand::MO_FPImmediate: { - OS << ' ' << toString(MO.getFPImm()->getValueAPF()); - } break; - case MachineOperand::MO_GlobalAddress: { - OS << ' ' << toSymbol(MO.getGlobal()->getName()); - } break; - case MachineOperand::MO_MachineBasicBlock: { - OS << ' ' << toSymbol(MO.getMBB()->getSymbol()->getName()); - } break; + case MachineOperand::MO_Register: + OS << regToString(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + OS << MO.getImm(); + break; + case MachineOperand::MO_FPImmediate: + OS << toString(MO.getFPImm()->getValueAPF()); + break; + case MachineOperand::MO_GlobalAddress: + OS << toSymbol(MO.getGlobal()->getName()); + break; + case MachineOperand::MO_MachineBasicBlock: + OS << toSymbol(MO.getMBB()->getSymbol()->getName()); + break; } - OS << ')'; + } + break; + } } - - if (NumDefs != 0) - OS << ')'; OutStreamer->EmitRawText(OS.str()); + + if (NumDefs != 0) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + OS << "\t" "set_local " + << regToString(MI->getOperand(0).getReg()) << ", " + "pop"; + OutStreamer->EmitRawText(OS.str()); + } } // Force static initialization. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 475d13ceefa..1c7d86b293a 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -370,6 +370,10 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments( ++ArgNo; } + // Record the number of arguments, since argument indices and local variable + // indices are in the same index space. + MF.getInfo<WebAssemblyFunctionInfo>()->setNumArguments(ArgNo); + return Chain; } @@ -450,5 +454,6 @@ SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op, MCSection *WebAssemblyTargetObjectFile::SelectSectionForGlobal( const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { - return getDataSection(); + // TODO: Be more sophisticated than this. + return isa<Function>(GV) ? getTextSection() : getDataSection(); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h index 22ef48116af..a571e63d7f6 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -27,9 +27,15 @@ namespace llvm { class WebAssemblyFunctionInfo final : public MachineFunctionInfo { MachineFunction &MF; + unsigned NumArguments; + public: - explicit WebAssemblyFunctionInfo(MachineFunction &MF) : MF(MF) {} + explicit WebAssemblyFunctionInfo(MachineFunction &MF) + : MF(MF), NumArguments(0) {} ~WebAssemblyFunctionInfo() override; + + void setNumArguments(unsigned N) { NumArguments = N; } + unsigned getNumArguments() const { return NumArguments; } }; } // end namespace llvm |