forked from llvm-mirror/llvm
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Func: add implementation of Chapter-3_2
- Loading branch information
Masayuki Kimura
committed
Dec 10, 2018
1 parent
5594042
commit 2997d95
Showing
24 changed files
with
951 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
//===-- Cpu0AsmPrinter.cpp - Cpu0 LLVM Assembly Printer -------------------===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file contains a printer that converts from our internal representation | ||
// of machine-dependent LLVM code to GAS-format CPU0 assembly language. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "Cpu0AsmPrinter.h" | ||
|
||
#include "InstPrinter/Cpu0InstPrinter.h" | ||
#include "MCTargetDesc/Cpu0BaseInfo.h" | ||
#include "Cpu0.h" | ||
#include "Cpu0InstrInfo.h" | ||
#include "llvm/ADT/SmallString.h" | ||
#include "llvm/ADT/StringExtras.h" | ||
#include "llvm/ADT/Twine.h" | ||
#include "llvm/CodeGen/MachineConstantPool.h" | ||
#include "llvm/CodeGen/MachineFunctionPass.h" | ||
#include "llvm/CodeGen/MachineFrameInfo.h" | ||
#include "llvm/CodeGen/MachineInstr.h" | ||
#include "llvm/CodeGen/MachineMemOperand.h" | ||
#include "llvm/IR/BasicBlock.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/IR/Mangler.h" | ||
#include "llvm/MC/MCAsmInfo.h" | ||
#include "llvm/MC/MCInst.h" | ||
#include "llvm/MC/MCStreamer.h" | ||
#include "llvm/MC/MCSymbol.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
#include "llvm/Support/TargetRegistry.h" | ||
#include "llvm/Target/TargetLoweringObjectFile.h" | ||
#include "llvm/Target/TargetOptions.h" | ||
|
||
using namespace llvm; | ||
|
||
#define DEBUG_TYPE "cpu0-asm-printer" | ||
|
||
bool Cpu0AsmPrinter::runOnMachineFunction(MachineFunction &MF) { | ||
Cpu0FI = MF.getInfo<Cpu0FunctionInfo>(); | ||
AsmPrinter::runOnMachineFunction(MF); | ||
return true; | ||
} | ||
|
||
//@EmitInstruction { | ||
//- EmitInstruction() must exists or will have run time error. | ||
void Cpu0AsmPrinter::EmitInstruction(const MachineInstr *MI) { | ||
//@EmitInstruction body { | ||
if (MI->isDebugValue()) { | ||
SmallString<128> Str; | ||
raw_svector_ostream OS(Str); | ||
|
||
PrintDebugValueComment(MI, OS); | ||
return; | ||
} | ||
|
||
//@print out instruction: | ||
// Print out both ordinary instruction and boudle instruction | ||
MachineBasicBlock::const_instr_iterator I = MI->getIterator(); | ||
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); | ||
|
||
do { | ||
|
||
if (I->isPseudo()) | ||
llvm_unreachable("Pseudo opcode found in EmitInstruction()"); | ||
|
||
MCInst TmpInst0; | ||
MCInstLowering.Lower(&*I, TmpInst0); | ||
OutStreamer->EmitInstruction(TmpInst0, getSubtargetInfo()); | ||
} while ((++I != E) && I->isInsideBundle()); // Delay slot check | ||
} | ||
//@EmitInstruction } | ||
|
||
//===----------------------------------------------------------------------===// | ||
// | ||
// Cpu0 Asm Directives | ||
// | ||
// -- Frame directive "frame Stackpointer, Stacksize, RARegister" | ||
// Describe the stack frame. | ||
// | ||
// -- Mask directives "(f)mask bitmask, offset" | ||
// Tells the assembler which registers are saved and where. | ||
// bitmask - contain a little endian bitset indicating which registers are | ||
// saved on function prologue (e.g. with a 0x80000000 mask, the | ||
// assembler knows the register 31 (RA) is saved at prologue. | ||
// offset - the position before stack pointer subtraction indicating where | ||
// the first saved register on prologue is located. (e.g. with a | ||
// | ||
// Consider the following function prologue: | ||
// | ||
// .frame $fp,48,$ra | ||
// .mask 0xc0000000,-8 | ||
// addiu $sp, $sp, -48 | ||
// st $ra, 40($sp) | ||
// st $fp, 36($sp) | ||
// | ||
// With a 0xc0000000 mask, the assembler knows the register 31 (RA) and | ||
// 30 (FP) are saved at prologue. As the save order on prologue is from | ||
// left to right, RA is saved first. A -8 offset means that after the | ||
// stack pointer subtration, the first register in the mask (RA) will be | ||
// saved at address 48-8=40. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Mask directives | ||
//===----------------------------------------------------------------------===// | ||
// .frame $sp,8,$lr | ||
//-> .mask 0x00000000,0 | ||
// .set noreorder | ||
// .set nomacro | ||
|
||
// Create a bitmask with all callee saved registers for CPU or Floating Point | ||
// registers. For CPU registers consider LR, GP and FP for saving if necessary. | ||
void Cpu0AsmPrinter::printSavedRegsBitmask(raw_ostream &O) { | ||
// CPU and FPU Saved Registers Bitmasks | ||
unsigned CPUBitmask = 0; | ||
int CPUTopSavedRegOff; | ||
|
||
// Set the CPU and FPU Bitmasks | ||
const MachineFrameInfo &MFI = MF->getFrameInfo(); | ||
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); | ||
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); | ||
// size of stack area to which FP callee-saved regs are saved. | ||
unsigned CPURegSize = TRI->getRegSizeInBits(Cpu0::CPURegsRegClass) / 8; | ||
unsigned i = 0, e = CSI.size(); | ||
|
||
// Set CPU Bitmask. | ||
for (; i != e; ++i) { | ||
unsigned Reg = CSI[i].getReg(); | ||
unsigned RegNum = TRI->getEncodingValue(Reg); | ||
CPUBitmask |= (1 << RegNum); | ||
} | ||
|
||
CPUTopSavedRegOff = CPUBitmask ? -CPURegSize : 0; | ||
|
||
// Print CPUBitmask | ||
O << "\t.mask \t"; printHex32(CPUBitmask, O); | ||
O << ',' << CPUTopSavedRegOff << '\n'; | ||
} | ||
|
||
// Print a 32 bit hex number with all numbers. | ||
void Cpu0AsmPrinter::printHex32(unsigned Value, raw_ostream &O) { | ||
O << "0x"; | ||
for (int i = 7; i >= 0; i--) | ||
O.write_hex((Value & (0xF << (i*4))) >> (i*4)); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Frame and Set directives | ||
//===----------------------------------------------------------------------===// | ||
//-> .frame $sp,8,$lr | ||
// .mask 0x00000000,0 | ||
// .set noreorder | ||
// .set nomacro | ||
/// Frame Directive | ||
void Cpu0AsmPrinter::emitFrameDirective() { | ||
const TargetRegisterInfo &RI = *MF->getSubtarget().getRegisterInfo(); | ||
|
||
unsigned stackReg = RI.getFrameRegister(*MF); | ||
unsigned returnReg = RI.getRARegister(); | ||
unsigned stackSize = MF->getFrameInfo().getStackSize(); | ||
|
||
if (OutStreamer->hasRawTextSupport()) | ||
OutStreamer->EmitRawText("\t.frame\t$" + | ||
StringRef(Cpu0InstPrinter::getRegisterName(stackReg)).lower() + | ||
"," + Twine(stackSize) + ",$" + | ||
StringRef(Cpu0InstPrinter::getRegisterName(returnReg)).lower()); | ||
} | ||
|
||
/// Emit Set directives. | ||
const char *Cpu0AsmPrinter::getCurrentABIString() const { | ||
switch (static_cast<Cpu0TargetMachine &>(TM).getABI().GetEnumValue()) { | ||
case Cpu0ABIInfo::ABI::O32: return "abiO32"; | ||
case Cpu0ABIInfo::ABI::S32: return "abiS32"; | ||
default: llvm_unreachable("Unknown Cpu0 ABI"); | ||
} | ||
} | ||
|
||
// .type main,@function | ||
//-> .ent main # @main | ||
// main: | ||
void Cpu0AsmPrinter::EmitFunctionEntryLabel() { | ||
if (OutStreamer->hasRawTextSupport()) | ||
OutStreamer->EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); | ||
OutStreamer->EmitLabel(CurrentFnSym); | ||
} | ||
|
||
// .frame $sp,8,$pc | ||
// .mask 0x00000000,0 | ||
//-> .set noreorder | ||
//@-> .set nomacro | ||
/// EmitFunctionBodyStart - Targets can override this to emit stuff before | ||
/// the first basic block in the function. | ||
void Cpu0AsmPrinter::EmitFunctionBodyStart() { | ||
MCInstLowering.Initialize(&MF->getContext()); | ||
|
||
emitFrameDirective(); | ||
|
||
if (OutStreamer->hasRawTextSupport()) { | ||
SmallString<128> Str; | ||
raw_svector_ostream OS(Str); | ||
printSavedRegsBitmask(OS); | ||
OutStreamer->EmitRawText(OS.str()); | ||
OutStreamer->EmitRawText(StringRef("\t.set\tnoreorder")); | ||
OutStreamer->EmitRawText(StringRef("\t.set\tnomacro")); | ||
if (Cpu0FI->getEmitNOAT()) | ||
OutStreamer->EmitRawText(StringRef("\t.set\tnoat")); | ||
} | ||
} | ||
|
||
//-> .set macro | ||
//-> .set reorder | ||
//-> .end main | ||
/// EmitFunctionBodyEnd - Targets can override this to emit stuff after | ||
/// the last basic block in the function. | ||
void Cpu0AsmPrinter::EmitFunctionBodyEnd() { | ||
// There are instruction for this macros, but they must | ||
// always be at the function end, and we can't emit and | ||
// break with BB logic. | ||
if (OutStreamer->hasRawTextSupport()) { | ||
if (Cpu0FI->getEmitNOAT()) | ||
OutStreamer->EmitRawText(StringRef("\t.set\tat")); | ||
OutStreamer->EmitRawText(StringRef("\t.set\tmacro")); | ||
OutStreamer->EmitRawText(StringRef("\t.set\treorder")); | ||
OutStreamer->EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); | ||
} | ||
} | ||
|
||
// .section .mdebug.abi32 | ||
// .previous | ||
void Cpu0AsmPrinter::EmitStartOfAsmFile(Module &M) { | ||
// FIXME: Use SwitchSection. | ||
|
||
// Tell the assembler which ABI we are using | ||
if (OutStreamer->hasRawTextSupport()) | ||
OutStreamer->EmitRawText("\t.section .mdebug." + | ||
Twine(getCurrentABIString())); | ||
|
||
// return to previous section | ||
if (OutStreamer->hasRawTextSupport()) | ||
OutStreamer->EmitRawText(StringRef("\t.previous")); | ||
} | ||
|
||
void Cpu0AsmPrinter::PrintDebugValueComment(const MachineInstr *MI, | ||
raw_ostream &OS) { | ||
// TODO: implement | ||
OS << "PrintDebugValueComment()"; | ||
} | ||
|
||
// Force static initialization. | ||
extern "C" void LLVMInitializeCpu0AsmPrinter() { | ||
RegisterAsmPrinter<Cpu0AsmPrinter> X(TheCpu0Target); | ||
RegisterAsmPrinter<Cpu0AsmPrinter> Y(TheCpu0elTarget); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
//===-- Cpu0AsmPrinter.h - Cpu0 LLVM Assembly Printer ----------*- C++ -*--===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Cpu0 Assembly printer class. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_LIB_TARGET_CPU0_CPU0ASMPRINTER_H | ||
#define LLVM_LIB_TARGET_CPU0_CPU0ASMPRINTER_H | ||
|
||
#include "Cpu0Config.h" | ||
|
||
#include "Cpu0MachineFunction.h" | ||
#include "Cpu0MCInstLower.h" | ||
#include "Cpu0Subtarget.h" | ||
#include "Cpu0TargetMachine.h" | ||
#include "llvm/CodeGen/AsmPrinter.h" | ||
#include "llvm/MC/MCStreamer.h" | ||
#include "llvm/Support/Compiler.h" | ||
#include "llvm/Target/TargetMachine.h" | ||
|
||
namespace llvm { | ||
class MCStreamer; | ||
class MachineInstr; | ||
class MachineBasicBlock; | ||
class Module; | ||
class raw_ostream; | ||
|
||
class LLVM_LIBRARY_VISIBILITY Cpu0AsmPrinter : public AsmPrinter { | ||
|
||
void EmitInstrWithMacroNoAT(const MachineInstr *MI); | ||
|
||
private: | ||
|
||
// lowerOperand - Convert a MachineOperand into the equivalent MCOperand. | ||
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp); | ||
|
||
public: | ||
|
||
const Cpu0Subtarget *Subtarget; | ||
const Cpu0FunctionInfo *Cpu0FI; | ||
Cpu0MCInstLower MCInstLowering; | ||
|
||
explicit Cpu0AsmPrinter(TargetMachine &TM, | ||
std::unique_ptr<MCStreamer> Streamer) | ||
: AsmPrinter(TM, std::move(Streamer)), | ||
MCInstLowering(*this) { | ||
Subtarget = static_cast<Cpu0TargetMachine &>(TM).getSubtargetImpl(); | ||
} | ||
|
||
StringRef getPassName() const override { return "Cpu0 Assembly Printer"; } | ||
|
||
virtual bool runOnMachineFunction(MachineFunction &MF) override; | ||
|
||
//- EmitInstruction() must exists or will have run time error. | ||
void EmitInstruction(const MachineInstr *MI) override; | ||
void printSavedRegsBitmask(raw_ostream &O); | ||
void printHex32(unsigned int Value, raw_ostream &O); | ||
void emitFrameDirective(); | ||
const char *getCurrentABIString() const; | ||
void EmitFunctionEntryLabel() override; | ||
void EmitFunctionBodyStart() override; | ||
void EmitFunctionBodyEnd() override; | ||
void EmitStartOfAsmFile(Module &M) override; | ||
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); | ||
}; | ||
} | ||
|
||
#endif | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.