Go to the documentation of this file.
51 #define DEBUG_TYPE "asm-printer"
66 LLVM_DEBUG(
errs() <<
"Unknown type for register number: " << RegNo);
74 "Unlowered physical register encountered during assembly printing");
76 unsigned WAReg = MFI->
getWAReg(RegNo);
78 return '$' + utostr(WAReg);
103 if (
Name.front() ==
'"' &&
Name.back() ==
'"')
105 return Name.startswith(
"__invoke_");
134 std::string
Ret =
"invoke_";
141 for (
unsigned I = 1,
E = Sig->
Params.size();
I <
E;
I++)
152 bool &InvokeDetected) {
156 InvokeDetected =
true;
159 "Emscripten EH/SjLj does not support multivalue returns: " +
160 std::string(
F->getName()) +
": " +
164 WasmSym = cast<MCSymbolWasm>(
214 if (WasmSym->getType().hasValue())
223 if (
Name ==
"__stack_pointer" ||
Name ==
"__tls_base" ||
224 Name ==
"__memory_base" ||
Name ==
"__table_base" ||
225 Name ==
"__tls_size" ||
Name ==
"__tls_align") {
227 Name ==
"__stack_pointer" ||
Name ==
"__tls_base";
236 if (
Name.startswith(
"GCC_except_table")) {
243 if (
Name ==
"__cpp_exception" ||
Name ==
"__c_longjmp") {
251 WasmSym->setWeak(
true);
252 WasmSym->setExternal(
true);
261 Params.push_back(AddrType);
266 auto Signature = std::make_unique<wasm::WasmSignature>(
std::move(Returns),
268 WasmSym->setSignature(Signature.get());
295 if (signaturesEmitted)
297 signaturesEmitted =
true;
306 if (WasmSym->isFunction()) {
317 auto Sym = cast<MCSymbolWasm>(It.getValue());
318 if (!Sym->isDefined())
323 for (
const auto &
F :
M) {
339 bool InvokeDetected =
false;
342 Signature.get(), InvokeDetected);
348 if (InvokeDetected && !InvokeSymbols.
insert(Sym).second)
352 if (!Sym->getSignature()) {
353 Sym->setSignature(Signature.get());
362 if (
F.hasFnAttribute(
"wasm-import-module")) {
364 F.getFnAttribute(
"wasm-import-module").getValueAsString();
365 Sym->setImportModule(storeName(
Name));
368 if (
F.hasFnAttribute(
"wasm-import-name")) {
374 :
F.getFnAttribute(
"wasm-import-name").getValueAsString();
375 Sym->setImportName(storeName(
Name));
379 if (
F.hasFnAttribute(
"wasm-export-name")) {
380 auto *Sym = cast<MCSymbolWasm>(
getSymbol(&
F));
381 StringRef Name =
F.getFnAttribute(
"wasm-export-name").getValueAsString();
382 Sym->setExportName(storeName(
Name));
400 for (
const auto &
F :
M) {
401 if (!
F.isIntrinsic() &&
F.hasAddressTaken()) {
409 for (
const auto &
G :
M.globals()) {
410 if (!
G.hasInitializer() &&
G.hasExternalLinkage() &&
412 G.getValueType()->isSized()) {
413 uint16_t Size =
M.getDataLayout().getTypeAllocSize(
G.getValueType());
419 if (
const NamedMDNode *Named =
M.getNamedMetadata(
"wasm.custom_sections")) {
420 for (
const Metadata *MD : Named->operands()) {
421 const auto *Tuple = dyn_cast<MDTuple>(MD);
422 if (!Tuple || Tuple->getNumOperands() != 2)
424 const MDString *
Name = dyn_cast<MDString>(Tuple->getOperand(0));
425 const MDString *Contents = dyn_cast<MDString>(Tuple->getOperand(1));
426 if (!
Name || !Contents)
430 std::string
SectionName = (
".custom_section." +
Name->getString()).str();
445 if (
const NamedMDNode *Debug =
M.getNamedMetadata(
"llvm.dbg.cu")) {
447 for (
size_t I = 0,
E = Debug->getNumOperands();
I <
E; ++
I) {
448 const auto *
CU = cast<DICompileUnit>(Debug->getOperand(
I));
457 if (
const NamedMDNode *Ident =
M.getNamedMetadata(
"llvm.ident")) {
459 for (
size_t I = 0,
E = Ident->getNumOperands();
I <
E; ++
I) {
460 const auto *
S = cast<MDString>(Ident->getOperand(
I)->getOperand(0));
461 std::pair<StringRef, StringRef>
Field =
S->getString().split(
"version");
469 int FieldCount =
int(!Languages.empty()) +
int(!Tools.empty());
470 if (FieldCount != 0) {
476 for (
auto &Producers : {std::make_pair(
"language", &Languages),
477 std::make_pair(
"processed-by", &Tools)}) {
478 if (Producers.second->empty())
480 OutStreamer->emitULEB128IntValue(strlen(Producers.first));
482 OutStreamer->emitULEB128IntValue(Producers.second->size());
483 for (
auto &Producer : *Producers.second) {
484 OutStreamer->emitULEB128IntValue(Producer.first.size());
486 OutStreamer->emitULEB128IntValue(Producer.second.size());
495 struct FeatureEntry {
502 auto EmitFeature = [&](std::string Feature) {
503 std::string MDKey = (
StringRef(
"wasm-feature-") + Feature).str();
504 Metadata *Policy =
M.getModuleFlag(MDKey);
505 if (Policy ==
nullptr)
510 Entry.Name = Feature;
512 if (
auto *MD = cast<ConstantAsMetadata>(Policy))
513 if (
auto *
I = cast<ConstantInt>(MD->getValue()))
514 Entry.Prefix =
I->getZExtValue();
522 EmittedFeatures.push_back(Entry);
529 EmitFeature(
"shared-mem");
534 if (
M.getDataLayout().getPointerSize() == 8) {
540 if (EmittedFeatures.size() == 0)
549 OutStreamer->emitULEB128IntValue(EmittedFeatures.size());
550 for (
auto &
F : EmittedFeatures) {
562 "WebAssembly disables constant pools");
577 WasmSym->setSignature(Signature.get());
584 if (
MDNode *Idx =
F.getMetadata(
"wasm.index")) {
585 assert(Idx->getNumOperands() == 1);
588 cast<ConstantAsMetadata>(Idx->getOperand(0))->getValue()));
601 switch (
MI->getOpcode()) {
602 case WebAssembly::ARGUMENT_i32:
603 case WebAssembly::ARGUMENT_i32_S:
604 case WebAssembly::ARGUMENT_i64:
605 case WebAssembly::ARGUMENT_i64_S:
606 case WebAssembly::ARGUMENT_f32:
607 case WebAssembly::ARGUMENT_f32_S:
608 case WebAssembly::ARGUMENT_f64:
609 case WebAssembly::ARGUMENT_f64_S:
610 case WebAssembly::ARGUMENT_v16i8:
611 case WebAssembly::ARGUMENT_v16i8_S:
612 case WebAssembly::ARGUMENT_v8i16:
613 case WebAssembly::ARGUMENT_v8i16_S:
614 case WebAssembly::ARGUMENT_v4i32:
615 case WebAssembly::ARGUMENT_v4i32_S:
616 case WebAssembly::ARGUMENT_v2i64:
617 case WebAssembly::ARGUMENT_v2i64_S:
618 case WebAssembly::ARGUMENT_v4f32:
619 case WebAssembly::ARGUMENT_v4f32_S:
620 case WebAssembly::ARGUMENT_v2f64:
621 case WebAssembly::ARGUMENT_v2f64_S:
625 case WebAssembly::FALLTHROUGH_RETURN: {
634 case WebAssembly::COMPILER_FENCE:
641 MCInstLowering.
lower(
MI, TmpInst);
650 const char *ExtraCode,
688 const char *ExtraCode,
virtual void emitLocal(ArrayRef< wasm::ValType > Types)=0
.local
@ WASM_FEATURE_PREFIX_USED
const WebAssemblyRegisterInfo * getRegisterInfo() const override
const SubtargetFeatureKV WebAssemblyFeatureKV[WebAssembly::NumSubtargetFeatures]
@ WASM_FEATURE_PREFIX_DISALLOWED
bool isPositionIndependent() const
cl::opt< bool > WasmKeepRegisters
@ MO_Immediate
Immediate operand.
This is an optimization pass for GlobalISel generic memory operations.
WebAssembly-specific streamer interface, to implement support WebAssembly-specific assembly directive...
void printOffset(int64_t Offset, raw_ostream &OS) const
This is just convenient handler for printing offsets.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
const std::vector< MVT > & getLocals() const
static SectionKind getMetadata()
virtual const MCExpr * lowerConstant(const Constant *CV)
Lower the specified LLVM Constant to an MCExpr.
Target & getTheWebAssemblyTarget32()
Optional< wasm::WasmSymbolType > getType() const
StringSet MachineSymbolsUsed
const SymbolTable & getSymbols() const
getSymbols - Get a reference for the symbol table for clients that want to, for example,...
virtual void emitIndIdx(const MCExpr *Value)=0
.indidx
const WebAssemblyTargetLowering * getTargetLowering() const override
const MCAsmInfo * MAI
Target Asm Printer information.
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
std::unique_ptr< wasm::WasmSignature > signatureFromMVTs(const SmallVectorImpl< MVT > &Results, const SmallVectorImpl< MVT > &Params)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
static bool isEmscriptenInvokeName(StringRef Name)
const WebAssemblySubtarget & getSubtarget() const
@ WASM_SYMBOL_TYPE_GLOBAL
std::string signatureToString(const wasm::WasmSignature *Sig)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
The instances of the Type class are immutable: once they are created, they are never changed.
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)
Print the MachineOperand as a symbol.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::string regToString(const MachineOperand &MO)
Function Alias Analysis Results
void wasmSymbolSetType(MCSymbolWasm *Sym, const Type *GlobalVT, const SmallVector< MVT, 1 > &VTs)
Sets a Wasm Symbol Type.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Instances of this class represent a single low-level machine instruction.
std::pair< iterator, bool > insert(const ValueT &V)
MCSymbol * getOrCreateWasmSymbol(StringRef Name)
int64_t getOffset() const
Return the offset from the symbol in this operand.
unsigned const TargetRegisterInfo * TRI
virtual void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule)=0
.import_module
This class is used to lower an MachineInstr into an MCInst.
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
@ MO_Register
Register operand.
bool hasInitializer() const
Definitions have initializers, declarations don't.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
@ INLINEASM
INLINEASM - Represents an inline asm block.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)
virtual void emitFunctionType(const MCSymbolWasm *Sym)=0
.functype
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
virtual void emitExportName(const MCSymbolWasm *Sym, StringRef ExportName)=0
.export_name
void lower(const MachineInstr *MI, MCInst &OutMI) const
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
StringRef LanguageString(unsigned Language)
virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const
This emits linkage information about GVSym based on GV, if this is supported by the target.
virtual void emitTableType(const MCSymbolWasm *Sym)=0
.tabletype
virtual void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName)=0
.import_name
@ MO_GlobalAddress
Address of a global value.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
constexpr char Language[]
Key for Kernel::Metadata::mLanguage.
This represents a section on wasm.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
void addSignature(std::unique_ptr< wasm::WasmSignature > &&Sig)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
MVT getRegType(unsigned RegNo) const
cl::opt< bool > WasmEnableEmSjLj
MachineOperand class - Representation of each machine instruction operand.
void emitJumpTableInfo() override
Print assembly representations of the jump tables used by the current function to the current output ...
MCSymbol * CurrentFnSym
The symbol for the current function.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class implements an extremely fast bulk output stream that can only output to a stream.
@ WASM_SYMBOL_TYPE_FUNCTION
Target specific streamer interface.
virtual void emitFunctionBodyStart()
Targets can override this to emit stuff before the first basic block in the function.
Used to provide key value pairs for feature and CPU bit flags.
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
MCSectionWasm * getWasmSection(const Twine &Section, SectionKind K, unsigned Flags=0)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
void EmitTargetFeatures(Module &M)
Implements a dense probed hash-table based set.
static const unsigned UnusedReg
void emitFunctionBodyStart() override
Targets can override this to emit stuff before the first basic block in the function.
Representation of each machine instruction.
VisibilityTypes getVisibility() const
Module * getParent()
Get the module that this global value is contained inside of...
#define LLVM_EXTERNAL_VISIBILITY
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
MCSymbol * getSymbolPreferLocal(const GlobalValue &GV) const
Similar to getSymbol() but preferred for references.
void valTypesFromMVTs(const ArrayRef< MVT > &In, SmallVectorImpl< wasm::ValType > &Out)
void getLibcallSignature(const WebAssemblySubtarget &Subtarget, RTLIB::Libcall LC, SmallVectorImpl< wasm::ValType > &Rets, SmallVectorImpl< wasm::ValType > &Params)
SmallVector< ValType, 1 > Returns
void EmitProducerInfo(Module &M)
@ WASM_FEATURE_PREFIX_REQUIRED
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
unsigned getWAReg(unsigned VReg) const
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
bool isVRegStackified(unsigned VReg) const
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MCSymbol * getSymbol(const GlobalValue *GV) const
constexpr const T & getValue() const &
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
MachineFunction * MF
The current machine function.
MCContext & OutContext
This is the context for the output file that we are streaming.
Register getReg() const
getReg - Returns the register number.
A Module instance is used to store all the information related to an LLVM module.
void emitDecls(const Module &M)
static char getInvokeSig(wasm::ValType VT)
void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI, LLVMContext &Ctx, const DataLayout &DL, Type *Ty, SmallVectorImpl< MVT > &ValueVTs)
MCSymbol * GetExternalSymbolSymbol(StringRef Sym) const
Return the MCSymbol for the specified ExternalSymbol.
MachineBasicBlock * getMBB() const
StringRef - Represent a constant reference to a string, i.e.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation for Wasm targets.
bool isTypeLegalForClass(const TargetRegisterClass &RC, MVT T) const
Return true if the given TargetRegisterClass has the ValueType T.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyAsmPrinter()
Wrapper class representing virtual and physical registers.
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Target & getTheWebAssemblyTarget64()
const CustomOperand< const MCSubtargetInfo & > Msg[]
WebAssemblyTargetStreamer * getTargetStreamer()
void emitConstantPool() override
Print to the current output stream assembly representations of the constants in the constant pool MCP...
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, const Function &ContextFunc, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
Function & getFunction()
Return the LLVM function that this machine code represents.
const std::vector< MachineConstantPoolEntry > & getConstants() const
@ MO_ExternalSymbol
Name of external global symbol.
LLVMContext & getContext() const
Get the global data context.
void emitGlobalVariable(const GlobalVariable *GV) override
Emit the specified global variable to the .s file.
MCSymbolWasm * getMCSymbolForFunction(const Function *F, bool EnableEmEH, wasm::WasmSignature *Sig, bool &InvokeDetected)
void emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition=true) const
This emits visibility information about symbol, if this is supported by the target.
unsigned getAddressSpace() const
void emitSymbolType(const MCSymbolWasm *Sym)
TargetMachine & TM
Target machine description.
const char * getSymbolName() const
bool isWasmVarAddressSpace(unsigned AS)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Type * getValueType() const
virtual void emitTagType(const MCSymbolWasm *Sym)=0
.tagtype
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
StringRef getString() const
bool isVerbose() const
Return true if assembly output should contain comments.
const Module * getModule() const
virtual void emitGlobalType(const MCSymbolWasm *Sym)=0
.globaltype
SmallVector< ValType, 4 > Params
static std::string getEmscriptenInvokeSymbolName(wasm::WasmSignature *Sig)
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
Ty & getObjFileInfo()
Keep track of various per-module pieces of information for backends that would like to do so.
cl::opt< bool > WasmEnableEmEH
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
reference emplace_back(ArgTypes &&... Args)