forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			114 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- AMDGPU.cpp ---------------------------------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "InputFiles.h"
 | |
| #include "Symbols.h"
 | |
| #include "Target.h"
 | |
| #include "lld/Common/ErrorHandler.h"
 | |
| #include "llvm/Object/ELF.h"
 | |
| #include "llvm/Support/Endian.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| using namespace llvm::object;
 | |
| using namespace llvm::support::endian;
 | |
| using namespace llvm::ELF;
 | |
| using namespace lld;
 | |
| using namespace lld::elf;
 | |
| 
 | |
| namespace {
 | |
| class AMDGPU final : public TargetInfo {
 | |
| public:
 | |
|   AMDGPU();
 | |
|   uint32_t calcEFlags() const override;
 | |
|   void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
 | |
|   RelExpr getRelExpr(RelType type, const Symbol &s,
 | |
|                      const uint8_t *loc) const override;
 | |
|   RelType getDynRel(RelType type) const override;
 | |
| };
 | |
| } // namespace
 | |
| 
 | |
| AMDGPU::AMDGPU() {
 | |
|   relativeRel = R_AMDGPU_RELATIVE64;
 | |
|   gotRel = R_AMDGPU_ABS64;
 | |
|   noneRel = R_AMDGPU_NONE;
 | |
|   symbolicRel = R_AMDGPU_ABS64;
 | |
| }
 | |
| 
 | |
| static uint32_t getEFlags(InputFile *file) {
 | |
|   return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader()->e_flags;
 | |
| }
 | |
| 
 | |
| uint32_t AMDGPU::calcEFlags() const {
 | |
|   assert(!objectFiles.empty());
 | |
|   uint32_t ret = getEFlags(objectFiles[0]);
 | |
| 
 | |
|   // Verify that all input files have the same e_flags.
 | |
|   for (InputFile *f : makeArrayRef(objectFiles).slice(1)) {
 | |
|     if (ret == getEFlags(f))
 | |
|       continue;
 | |
|     error("incompatible e_flags: " + toString(f));
 | |
|     return 0;
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| void AMDGPU::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
 | |
|   switch (type) {
 | |
|   case R_AMDGPU_ABS32:
 | |
|   case R_AMDGPU_GOTPCREL:
 | |
|   case R_AMDGPU_GOTPCREL32_LO:
 | |
|   case R_AMDGPU_REL32:
 | |
|   case R_AMDGPU_REL32_LO:
 | |
|     write32le(loc, val);
 | |
|     break;
 | |
|   case R_AMDGPU_ABS64:
 | |
|   case R_AMDGPU_REL64:
 | |
|     write64le(loc, val);
 | |
|     break;
 | |
|   case R_AMDGPU_GOTPCREL32_HI:
 | |
|   case R_AMDGPU_REL32_HI:
 | |
|     write32le(loc, val >> 32);
 | |
|     break;
 | |
|   default:
 | |
|     llvm_unreachable("unknown relocation");
 | |
|   }
 | |
| }
 | |
| 
 | |
| RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s,
 | |
|                            const uint8_t *loc) const {
 | |
|   switch (type) {
 | |
|   case R_AMDGPU_ABS32:
 | |
|   case R_AMDGPU_ABS64:
 | |
|     return R_ABS;
 | |
|   case R_AMDGPU_REL32:
 | |
|   case R_AMDGPU_REL32_LO:
 | |
|   case R_AMDGPU_REL32_HI:
 | |
|   case R_AMDGPU_REL64:
 | |
|     return R_PC;
 | |
|   case R_AMDGPU_GOTPCREL:
 | |
|   case R_AMDGPU_GOTPCREL32_LO:
 | |
|   case R_AMDGPU_GOTPCREL32_HI:
 | |
|     return R_GOT_PC;
 | |
|   default:
 | |
|     error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
 | |
|           ") against symbol " + toString(s));
 | |
|     return R_NONE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| RelType AMDGPU::getDynRel(RelType type) const {
 | |
|   if (type == R_AMDGPU_ABS64)
 | |
|     return type;
 | |
|   return R_AMDGPU_NONE;
 | |
| }
 | |
| 
 | |
| TargetInfo *elf::getAMDGPUTargetInfo() {
 | |
|   static AMDGPU target;
 | |
|   return ⌖
 | |
| }
 |