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

JF Bastien via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 16:07:41 PDT 2015


On Wed, Aug 26, 2015 at 3:56 PM, Dan Gohman <sunfish at mozilla.com> wrote:

>
>
> 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?
>

Ignore it for now, I'm not sure there's point in translating it in the
future, but we'll see when we get there.


> +  // 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.
>

Fixed.

+  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.
>

I'm expecting us to separately write a pass which linearizes the heap, and
leaves the non-address-taken globals around for this code to handle. It
seems easier to get basic things running by having globals first (instead
of proper linearization). WDYT?


> +  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.
>

I keyed off  XCore's AsmPrinter as well as the basic one, it seems to do
the basic that spec/forward.wasm wants :-)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150826/cdd676cc/attachment.html>


More information about the llvm-commits mailing list