Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -519,11 +519,15 @@ if (!IsConstantImm) { IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI || - VK == RISCVMCExpr::VK_RISCV_GOT_HI); + VK == RISCVMCExpr::VK_RISCV_GOT_HI || + VK == RISCVMCExpr::VK_RISCV_TLS_IE_HI || + VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI); } else { return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_PCREL_HI || - VK == RISCVMCExpr::VK_RISCV_GOT_HI); + VK == RISCVMCExpr::VK_RISCV_GOT_HI || + VK == RISCVMCExpr::VK_RISCV_TLS_IE_HI || + VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI); } } @@ -877,8 +881,9 @@ case Match_InvalidUImm20AUIPC: return generateImmOutOfRangeError( Operands, ErrorInfo, 0, (1 << 20) - 1, - "operand must be a symbol with %pcrel_hi/%got_pcrel_hi() modifier or an " - "integer in the range"); + "operand must be a symbol with " + "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi() modifier " + "or an integer in the range"); case Match_InvalidSImm21Lsb0JAL: return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2, Index: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -81,10 +81,12 @@ { "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_riscv_tls_ie_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_tprel_hi20", 12, 20, 0 }, { "fixup_riscv_tprel_lo12_i", 20, 12, 0 }, { "fixup_riscv_tprel_lo12_s", 0, 32, 0 }, { "fixup_riscv_tprel_add", 0, 0, 0 }, + { "fixup_riscv_tls_gd_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel }, Index: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -176,7 +176,9 @@ case RISCV::fixup_riscv_hi20: case RISCV::fixup_riscv_pcrel_hi20: case RISCV::fixup_riscv_got_hi20: + case RISCV::fixup_riscv_tls_ie_hi20: case RISCV::fixup_riscv_tprel_hi20: + case RISCV::fixup_riscv_tls_gd_hi20: // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative. return ((Value + 0x800) >> 12) & 0xfffff; case RISCV::fixup_riscv_jal: { Index: lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -86,6 +86,8 @@ return ELF::R_RISCV_PCREL_LO12_S; case RISCV::fixup_riscv_got_hi20: return ELF::R_RISCV_GOT_HI20; + case RISCV::fixup_riscv_tls_ie_hi20: + return ELF::R_RISCV_TLS_GOT_HI20; case RISCV::fixup_riscv_tprel_hi20: return ELF::R_RISCV_TPREL_HI20; case RISCV::fixup_riscv_tprel_lo12_i: @@ -94,6 +96,8 @@ return ELF::R_RISCV_TPREL_LO12_S; case RISCV::fixup_riscv_tprel_add: return ELF::R_RISCV_TPREL_ADD; + case RISCV::fixup_riscv_tls_gd_hi20: + return ELF::R_RISCV_TLS_GD_HI20; case RISCV::fixup_riscv_jal: return ELF::R_RISCV_JAL; case RISCV::fixup_riscv_branch: Index: lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h +++ lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h @@ -38,6 +38,9 @@ // fixup_riscv_got_hi20 - 20-bit fixup corresponding to got_pcrel_hi(foo) for // instructions like auipc fixup_riscv_got_hi20, + // fixup_riscv_tls_ie_hi20 - 20-bit fixup corresponding to + // tls_ie_pcrel_hi(foo) for instructions like auipc + fixup_riscv_tls_ie_hi20, // fixup_riscv_tprel_hi20 - 20-bit fixup corresponding to tprel_hi(foo) for // instructions like lui fixup_riscv_tprel_hi20, @@ -50,6 +53,9 @@ // fixup_riscv_tprel_add - A fixup corresponding to %tprel_add(foo) for the // add_tls instruction. Used to provide a hint to the linker. fixup_riscv_tprel_add, + // fixup_riscv_tls_gd_hi20 - 20-bit fixup corresponding to + // tls_gd_pcrel_hi(foo) for instructions like auipc + fixup_riscv_tls_gd_hi20, // fixup_riscv_jal - 20-bit fixup for symbol references in the jal // instruction fixup_riscv_jal, Index: lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -286,6 +286,9 @@ case RISCVMCExpr::VK_RISCV_GOT_HI: FixupKind = RISCV::fixup_riscv_got_hi20; break; + case RISCVMCExpr::VK_RISCV_TLS_IE_HI: + FixupKind = RISCV::fixup_riscv_tls_ie_hi20; + break; case RISCVMCExpr::VK_RISCV_TPREL_LO: if (MIFrm == RISCVII::InstFormatI) FixupKind = RISCV::fixup_riscv_tprel_lo12_i; @@ -298,6 +301,9 @@ case RISCVMCExpr::VK_RISCV_TPREL_HI: FixupKind = RISCV::fixup_riscv_tprel_hi20; break; + case RISCVMCExpr::VK_RISCV_TLS_GD_HI: + FixupKind = RISCV::fixup_riscv_tls_gd_hi20; + break; case RISCVMCExpr::VK_RISCV_CALL: FixupKind = RISCV::fixup_riscv_call; break; Index: lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h +++ lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h @@ -30,9 +30,11 @@ VK_RISCV_PCREL_LO, VK_RISCV_PCREL_HI, VK_RISCV_GOT_HI, + VK_RISCV_TLS_IE_HI, VK_RISCV_TPREL_LO, VK_RISCV_TPREL_HI, VK_RISCV_TPREL_ADD, + VK_RISCV_TLS_GD_HI, VK_RISCV_CALL, VK_RISCV_CALL_PLT, VK_RISCV_Invalid Index: lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -137,9 +137,11 @@ case VK_RISCV_PCREL_LO: case VK_RISCV_PCREL_HI: case VK_RISCV_GOT_HI: + case VK_RISCV_TLS_IE_HI: case VK_RISCV_TPREL_LO: case VK_RISCV_TPREL_HI: case VK_RISCV_TPREL_ADD: + case VK_RISCV_TLS_GD_HI: return false; } } @@ -158,9 +160,11 @@ .Case("pcrel_lo", VK_RISCV_PCREL_LO) .Case("pcrel_hi", VK_RISCV_PCREL_HI) .Case("got_pcrel_hi", VK_RISCV_GOT_HI) + .Case("tls_ie_pcrel_hi", VK_RISCV_TLS_IE_HI) .Case("tprel_lo", VK_RISCV_TPREL_LO) .Case("tprel_hi", VK_RISCV_TPREL_HI) .Case("tprel_add", VK_RISCV_TPREL_ADD) + .Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI) .Default(VK_RISCV_Invalid); } @@ -178,12 +182,16 @@ return "pcrel_hi"; case VK_RISCV_GOT_HI: return "got_pcrel_hi"; + case VK_RISCV_TLS_IE_HI: + return "tls_ie_pcrel_hi"; case VK_RISCV_TPREL_LO: return "tprel_lo"; case VK_RISCV_TPREL_HI: return "tprel_hi"; case VK_RISCV_TPREL_ADD: return "tprel_add"; + case VK_RISCV_TLS_GD_HI: + return "tls_gd_pcrel_hi"; } } @@ -220,7 +228,9 @@ switch (getKind()) { default: return; + case VK_RISCV_TLS_IE_HI: case VK_RISCV_TPREL_HI: + case VK_RISCV_TLS_GD_HI: break; } @@ -231,8 +241,9 @@ MCValue Value; if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO || - Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI || - Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD || + Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TLS_IE_HI || + Kind == VK_RISCV_TPREL_HI || Kind == VK_RISCV_TPREL_LO || + Kind == VK_RISCV_TPREL_ADD || Kind == VK_RISCV_TLS_GD_HI || Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT) return false; Index: test/MC/RISCV/rv32i-invalid.s =================================================================== --- test/MC/RISCV/rv32i-invalid.s +++ test/MC/RISCV/rv32i-invalid.s @@ -40,7 +40,7 @@ ## uimm20 lui a0, -1 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi() modifier or an integer in the range [0, 1048575] lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi() modifier or an integer in the range [0, 1048575] -auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi() modifier or an integer in the range [0, 1048575] ## simm21_lsb0 jal gp, -1048578 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] @@ -105,7 +105,7 @@ ## uimm20 lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi() modifier or an integer in the range [0, 1048575] -auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi() modifier or an integer in the range [0, 1048575] ## simm21_lsb0 jal gp, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] @@ -125,10 +125,10 @@ lui a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi() modifier or an integer in the range [0, 1048575] lui a0, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi() modifier or an integer in the range [0, 1048575] -auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi() modifier or an integer in the range [0, 1048575] -auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi() modifier or an integer in the range [0, 1048575] -auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi() modifier or an integer in the range [0, 1048575] -auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi() modifier or an integer in the range [0, 1048575] # TP-relative symbol names require a %tprel_add modifier. add a0, a0, tp, zero # CHECK: :[[@LINE]]:17: error: operand must be a symbol with %tprel_add modifier Index: test/MC/RISCV/rv32i-valid.s =================================================================== --- test/MC/RISCV/rv32i-valid.s +++ test/MC/RISCV/rv32i-valid.s @@ -63,6 +63,16 @@ # CHECK-OBJ: auipc a0, 0 # CHECK-OBJ: R_RISCV_GOT_HI20 foo auipc a0, %got_pcrel_hi(foo) +# CHECK-ASM: auipc a0, %tls_ie_pcrel_hi(foo) +# CHECK-ASM: encoding: [0x17,0bAAAA0101,A,A] +# CHECK-OBJ: auipc a0, 0 +# CHECK-OBJ: R_RISCV_TLS_GOT_HI20 foo +auipc a0, %tls_ie_pcrel_hi(foo) +# CHECK-ASM: auipc a0, %tls_gd_pcrel_hi(foo) +# CHECK-ASM: encoding: [0x17,0bAAAA0101,A,A] +# CHECK-OBJ: auipc a0, 0 +# CHECK-OBJ: R_RISCV_TLS_GD_HI20 foo +auipc a0, %tls_gd_pcrel_hi(foo) # CHECK-ASM-AND-OBJ: jal a2, 1048574 # CHECK-ASM: encoding: [0x6f,0xf6,0xff,0x7f]