[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