[llvm] r246092 - WebAssembly: handle private/internal globals.

Dan Gohman via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 15:56:30 PDT 2015


On Wed, Aug 26, 2015 at 3:09 PM, JF Bastien via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: jfb
> Date: Wed Aug 26 17:09:54 2015
> New Revision: 246092
>
> URL: http://llvm.org/viewvc/llvm-project?rev=246092&view=rev
> Log:
> 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.
>
> Added:
>     llvm/trunk/test/CodeGen/WebAssembly/global.ll
> Modified:
>     llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
>
> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp?rev=246092&r1=246091&r2=246092&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (original)
> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp Wed Aug 26
> 17:09:54 2015
> @@ -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 WebAss
>
>  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;
>

Are you proposing that we always ignore "llvm.used" or just ignore it
temporarily?


> +  // 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", since we likely will support some of these eventually.


> +  default:
> +    llvm_unreachable("Unknown linkage type");
> +    return;
> +  }
> +
> +  OS << "(global " << toSymbol(Name) << ' ' << toString(Init->getType())
> << ' ';
>

If this is creating a wasm global variable, it isn't correct since wasm
global variables aren't in linear memory, while C++ global variables are.


> +  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::EmitFunction
>    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::EmitInstruct
>      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::EmitInstruct
>        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());
>
>
I'm surprised there's no GVSym = getSymbol(GV),
GVSym->redefineIfPossible(), and so on, and am surprised that to see
handling for things like initializers. I had expected we would just leave
everything in data sections, like LLVM usually does, especially for now.

Dan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150826/f9db41c6/attachment-0001.html>


More information about the llvm-commits mailing list