Index: lib/MC/MCParser/WasmAsmParser.cpp =================================================================== --- lib/MC/MCParser/WasmAsmParser.cpp +++ lib/MC/MCParser/WasmAsmParser.cpp @@ -56,6 +56,15 @@ addDirectiveHandler<&WasmAsmParser::parseSectionDirective>(".section"); addDirectiveHandler<&WasmAsmParser::parseDirectiveSize>(".size"); addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type"); + addDirectiveHandler<&WasmAsmParser::ParseDirectiveIdent>(".ident"); + addDirectiveHandler< + &WasmAsmParser::ParseDirectiveSymbolAttribute>(".weak"); + addDirectiveHandler< + &WasmAsmParser::ParseDirectiveSymbolAttribute>(".local"); + addDirectiveHandler< + &WasmAsmParser::ParseDirectiveSymbolAttribute>(".internal"); + addDirectiveHandler< + &WasmAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); } bool error(const StringRef &Msg, const AsmToken &Tok) { @@ -198,6 +207,51 @@ Lex(); return expect(AsmToken::EndOfStatement, "EOL"); } + + // FIXME: Shared with ELF. + /// ParseDirectiveIdent + /// ::= .ident string + bool ParseDirectiveIdent(StringRef, SMLoc) { + if (getLexer().isNot(AsmToken::String)) + return TokError("unexpected token in '.ident' directive"); + StringRef Data = getTok().getIdentifier(); + Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.ident' directive"); + Lex(); + getStreamer().EmitIdent(Data); + return false; + } + + // FIXME: Shared with ELF. + /// ParseDirectiveSymbolAttribute + /// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ] + bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { + MCSymbolAttr Attr = StringSwitch(Directive) + .Case(".weak", MCSA_Weak) + .Case(".local", MCSA_Local) + .Case(".hidden", MCSA_Hidden) + .Case(".internal", MCSA_Internal) + .Case(".protected", MCSA_Protected) + .Default(MCSA_Invalid); + assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + while (true) { + StringRef Name; + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in directive"); + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + getStreamer().EmitSymbolAttribute(Sym, Attr); + if (getLexer().is(AsmToken::EndOfStatement)) + break; + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + Lex(); + return false; + } }; } // end anonymous namespace Index: test/MC/WebAssembly/basic-assembly.s =================================================================== --- test/MC/WebAssembly/basic-assembly.s +++ test/MC/WebAssembly/basic-assembly.s @@ -50,14 +50,14 @@ br_table {0, 1, 2} # 2 entries, default end_block # first entry jumps here. i32.const 1 - br 2 + br 2 end_block # second entry jumps here. i32.const 2 - br 1 + br 1 end_block # default jumps here. i32.const 3 end_block # "switch" exit. - if # void + if # void if i32 end_if else @@ -72,32 +72,34 @@ atomic.notify 0 .LBB0_3: catch - local.set 0 + local.set 0 block i32 - local.get 0 - br_on_exn 0, __cpp_exception + local.get 0 + br_on_exn 0, __cpp_exception rethrow .LBB0_4: end_block end_try - i32.const .L.str + i32.const .L.str throw 0 .LBB0_5: #i32.trunc_sat_f32_s global.get __stack_pointer end_function - .section .rodata..L.str,"",@ + .section .rodata..L.str,"",@ + .hidden .L.str .L.str: - .int8 'H' - .asciz "ello, World!" - .size .L.str, 14 + .int8 'H' + .asciz "ello, World!" + .size .L.str, 14 - .globaltype __stack_pointer, i32 + .ident "clang version 9.0.0 (trunk 364502) (llvm/trunk 364571)" + .globaltype __stack_pointer, i32 # CHECK: .text # CHECK-LABEL: test0: -# CHECK-NEXT: .functype test0 (i32, i64) -> (i32) +# CHECK-NEXT: .functype test0 (i32, i64) -> (i32) # CHECK-NEXT: .eventtype __cpp_exception i32 # CHECK-NEXT: .local f32, f64 # CHECK-NEXT: local.get 2 @@ -113,9 +115,9 @@ # CHECK-NEXT: i32.const 1 # CHECK-NEXT: local.get 0 # CHECK-NEXT: i32.ge_s -# CHECK-NEXT: br_if 0 # 0: down to label0 +# CHECK-NEXT: br_if 0 # 0: down to label0 # CHECK-NEXT: .LBB0_1: -# CHECK-NEXT: loop i32 # label1: +# CHECK-NEXT: loop i32 # label1: # CHECK-NEXT: call something1 # CHECK-NEXT: i64.const 1234 # CHECK-NEXT: i32.call something2 @@ -126,10 +128,10 @@ # CHECK-NEXT: local.tee 0 # CHECK-NEXT: local.get 0 # CHECK-NEXT: i32.lt_s -# CHECK-NEXT: br_if 0 # 0: up to label1 +# CHECK-NEXT: br_if 0 # 0: up to label1 # CHECK-NEXT: .LBB0_2: # CHECK-NEXT: end_loop -# CHECK-NEXT: end_block # label0: +# CHECK-NEXT: end_block # label0: # CHECK-NEXT: local.get 4 # CHECK-NEXT: local.get 5 # CHECK-NEXT: block @@ -139,13 +141,13 @@ # CHECK-NEXT: br_table {0, 1, 2} # 1: down to label4 # CHECK-NEXT: # 2: down to label3 # CHECK-NEXT: end_block # label5: -# CHECK-NEXT: i32.const 1 -# CHECK-NEXT: br 2 # 2: down to label2 +# CHECK-NEXT: i32.const 1 +# CHECK-NEXT: br 2 # 2: down to label2 # CHECK-NEXT: end_block # label4: -# CHECK-NEXT: i32.const 2 -# CHECK-NEXT: br 1 # 1: down to label2 +# CHECK-NEXT: i32.const 2 +# CHECK-NEXT: br 1 # 1: down to label2 # CHECK-NEXT: end_block # label3: -# CHECK-NEXT: i32.const 3 +# CHECK-NEXT: i32.const 3 # CHECK-NEXT: end_block # label2: # CHECK-NEXT: if # CHECK-NEXT: if i32 @@ -159,23 +161,24 @@ # CHECK-NEXT: atomic.notify 0 # CHECK-NEXT: .LBB0_3: # CHECK-NEXT: catch -# CHECK-NEXT: local.set 0 +# CHECK-NEXT: local.set 0 # CHECK-NEXT: block i32 -# CHECK-NEXT: local.get 0 -# CHECK-NEXT: br_on_exn 0, __cpp_exception +# CHECK-NEXT: local.get 0 +# CHECK-NEXT: br_on_exn 0, __cpp_exception # CHECK-NEXT: rethrow # CHECK-NEXT: .LBB0_4: # CHECK-NEXT: end_block # CHECK-NEXT: end_try -# CHECK-NEXT: i32.const .L.str -# CHECK-NEXT: throw 0 +# CHECK-NEXT: i32.const .L.str +# CHECK-NEXT: throw 0 # CHECK-NEXT: .LBB0_5: # CHECK-NEXT: global.get __stack_pointer # CHECK-NEXT: end_function -# CHECK: .section .rodata..L.str,"",@ -# CHECK-NEXT:.L.str: -# CHECK-NEXT: .int8 72 -# CHECK-NEXT: .asciz "ello, World!" +# CHECK: .section .rodata..L.str,"",@ +# CHECK-NEXT: .hidden .L.str +# CHECK-NEXT: .L.str: +# CHECK-NEXT: .int8 72 +# CHECK-NEXT: .asciz "ello, World!" -# CHECK: .globaltype __stack_pointer, i32 +# CHECK: .globaltype __stack_pointer, i32