summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
diff options
context:
space:
mode:
authorJF Bastien <jfb@google.com>2015-08-26 22:09:54 +0000
committerJF Bastien <jfb@google.com>2015-08-26 22:09:54 +0000
commit45479f627a91a0f3be7274b34e269d5b0cb48a90 (patch)
treed0cad42051927df259b14e7f985b2ba855c2a1a5 /llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
parentf50b20d81979170f8c8fe74b369b8f2f6b3de8f5 (diff)
downloadbcm5719-llvm-45479f627a91a0f3be7274b34e269d5b0cb48a90.tar.gz
bcm5719-llvm-45479f627a91a0f3be7274b34e269d5b0cb48a90.zip
WebAssembly: handle private/internal globals.
Things of note: - Other linkage types aren't handled yet. We'll figure it out with dynamic linking. - Special LLVM globals are either ignored, or error out for now. - TLS isn't supported yet (WebAssembly will have threads later). - There currently isn't a syntax for alignment, I left it in a comment so it's easy to hook up. - Undef is convereted to whatever the type's appropriate null value is. - assert versus report_fatal_error: follow what other AsmPrinters do, and assert only on what should have been caught elsewhere. llvm-svn: 246092
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp118
1 files changed, 96 insertions, 22 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index aa7734118a6..ea42470ab00 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -68,6 +68,8 @@ private:
// AsmPrinter Implementation.
//===------------------------------------------------------------------===//
+ void EmitGlobalVariable(const GlobalVariable *GV) override;
+
void EmitConstantPool() override;
void EmitFunctionEntryLabel() override;
void EmitFunctionBodyStart() override;
@@ -79,12 +81,14 @@ private:
} // end anonymous namespace
//===----------------------------------------------------------------------===//
+// 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> Name(const WebAssemblyInstrInfo *TII,
- const MachineInstr *MI) {
+static SmallString<32> 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;
@@ -93,7 +97,7 @@ static SmallString<32> Name(const WebAssemblyInstrInfo *TII,
static std::string toSymbol(StringRef S) { return ("$" + S).str(); }
-static const char *toType(const Type *Ty) {
+static const char *toString(const Type *Ty) {
switch (Ty->getTypeID()) {
default: break;
case Type::FloatTyID: return "f32";
@@ -110,6 +114,91 @@ static const char *toType(const Type *Ty) {
return "<invalid>";
}
+static std::string toString(const APFloat &FP) {
+ static const size_t BufBytes = 128;
+ char buf[BufBytes];
+ if (FP.isNaN())
+ assert((FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) ||
+ FP.bitwiseIsEqual(
+ APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) &&
+ "convertToHexString handles neither SNaN nor NaN payloads");
+ // Use C99's hexadecimal floating-point representation.
+ auto Written = FP.convertToHexString(
+ buf, /*hexDigits=*/0, /*upperCase=*/false, APFloat::rmNearestTiesToEven);
+ (void)Written;
+ assert(Written != 0);
+ assert(Written < BufBytes);
+ return buf;
+}
+
+//===----------------------------------------------------------------------===//
+// 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");
+ 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 << "\n";
+ OutStreamer->EmitRawText(OS.str());
+}
+
void WebAssemblyAsmPrinter::EmitConstantPool() {
assert(MF->getConstantPool()->getConstants().empty() &&
"WebAssembly disables constant pools");
@@ -139,10 +228,10 @@ void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
raw_svector_ostream OS(Str);
const Function *F = MF->getFunction();
for (const Argument &A : F->args())
- OS << " (param " << toType(A.getType()) << ')';
+ OS << " (param " << toString(A.getType()) << ')';
const Type *Rt = F->getReturnType();
if (!Rt->isVoidTy())
- OS << " (result " << toType(Rt) << ')';
+ OS << " (result " << toString(Rt) << ')';
OS << '\n';
OutStreamer->EmitRawText(OS.str());
}
@@ -171,7 +260,7 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
OS << "(setlocal @" << TargetRegisterInfo::virtReg2Index(Reg) << ' ';
}
- OS << '(' << Name(TII, MI);
+ OS << '(' << OpcodeName(TII, MI);
for (const MachineOperand &MO : MI->uses())
switch (MO.getType()) {
default:
@@ -186,22 +275,7 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
OS << ' ' << MO.getImm();
} break;
case MachineOperand::MO_FPImmediate: {
- static const size_t BufBytes = 128;
- char buf[BufBytes];
- APFloat FP = MO.getFPImm()->getValueAPF();
- if (FP.isNaN())
- assert((FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) ||
- FP.bitwiseIsEqual(
- APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) &&
- "convertToHexString handles neither SNaN nor NaN payloads");
- // Use C99's hexadecimal floating-point representation.
- auto Written =
- FP.convertToHexString(buf, /*hexDigits=*/0, /*upperCase=*/false,
- APFloat::rmNearestTiesToEven);
- (void)Written;
- assert(Written != 0);
- assert(Written < BufBytes);
- OS << ' ' << buf;
+ OS << ' ' << toString(MO.getFPImm()->getValueAPF());
} break;
case MachineOperand::MO_GlobalAddress: {
OS << ' ' << toSymbol(MO.getGlobal()->getName());
OpenPOWER on IntegriCloud