text:
This document describes techniques for writing compiler backends that convert the LLVM IR (intermediate representation) to code for a specified machine or other languages. Code intended for a specific machine can take the form of either assembly code or binary code (usable for a JIT compiler).
The backend of LLVM features a target-independent code generator that may create output for several types of target CPUs, including X86, PowerPC, Alpha, and SPARC. The backend may also be used to generate code targeted at SPUs of the Cell processor or GPUs to support the execution of compute kernels.
The document focuses on existing examples found in subdirectories of llvm/lib/Target in a downloaded LLVM release. In particular, this document focuses on the example of creating a static compiler (one that emits text assembly) for a SPARC target, because SPARC has fairly standard characteristics, such as a RISC instruction set and straightforward calling conventions.
The audience for this document is anyone who needs to write an LLVM backend to generate code for a specific hardware or software target.
To write a compiler backend for LLVM that converts the LLVM IR (intermediate representation) to code for a specified target (machine or other language), follow these steps:
In the .cpp and .h files, initially stub up these methods and then implement them later. Initially, you may not know which private members that the class will need and which components will need to be subclassed.
To actually create your compiler backend, you need to create and modify a few files. The absolute minimum is discussed here, but to actually use the LLVM target-independent code generator, you must perform the steps described in the LLVM Target-Independent Code Generator document.
First, you should create a subdirectory under lib/Target to hold all the files related to your target. If your target is called "Dummy", create the directory lib/Target/Dummy.
In this new directory, create a Makefile. It is easiest to copy a Makefile of another target and modify it. It should at least contain the LEVEL, LIBRARYNAME and TARGET variables, and then include $(LEVEL)/Makefile.common. The library can be named LLVMDummy (for example, see the MIPS target). Alternatively, you can split the library into LLVMDummyCodeGen and LLVMDummyAsmPrinter, the latter of which should be implemented in a subdirectory below lib/Target/Dummy (for example, see the PowerPC target).
Note that these two naming schemes are hardcoded into llvm-config. Using any other naming scheme will confuse llvm-config and produce lots of (seemingly unrelated) linker errors when linking llc.
To make your target actually do something, you need to implement a subclass of TargetMachine. This implementation should typically be in the file lib/Target/DummyTargetMachine.cpp, but any file in the lib/Target directory will be built and should work. To use LLVM's target independent code generator, you should do what all current machine backends do: create a subclass of LLVMTargetMachine. (To create a target from scratch, create a subclass of TargetMachine.)
To get LLVM to actually build and link your target, you need to add it to the TARGETS_TO_BUILD variable. To do this, you modify the configure script to know about your target when parsing the --enable-targets option. Search the configure script for TARGETS_TO_BUILD, add your target to the lists there (some creativity required) and then reconfigure. Alternatively, you can change autotools/configure.ac and regenerate configure by running ./autoconf/AutoRegen.sh
LLVMTargetMachine is designed as a base class for targets implemented with the LLVM target-independent code generator. The LLVMTargetMachine class should be specialized by a concrete target class that implements the various virtual methods. LLVMTargetMachine is defined as a subclass of TargetMachine in include/llvm/Target/TargetMachine.h. The TargetMachine class implementation (TargetMachine.cpp) also processes numerous command-line options.
To create a concrete target-specific subclass of LLVMTargetMachine, start by copying an existing TargetMachine class and header. You should name the files that you create to reflect your specific target. For instance, for the SPARC target, name the files SparcTargetMachine.h and SparcTargetMachine.cpp
For a target machine XXX, the implementation of XXXTargetMachine must have access methods to obtain objects that represent target components. These methods are named get*Info and are intended to obtain the instruction set (getInstrInfo), register set (getRegisterInfo), stack frame layout (getFrameInfo), and similar information. XXXTargetMachine must also implement the getTargetData method to access an object with target-specific data characteristics, such as data type size and alignment requirements.
For instance, for the SPARC target, the header file SparcTargetMachine.h declares prototypes for several get*Info and getTargetData methods that simply return a class member.
namespace llvm { class Module; class SparcTargetMachine : public LLVMTargetMachine { const TargetData DataLayout; // Calculates type size & alignment SparcSubtarget Subtarget; SparcInstrInfo InstrInfo; TargetFrameInfo FrameInfo; protected: virtual const TargetAsmInfo *createTargetAsmInfo() const; public: SparcTargetMachine(const Module &M, const std::string &FS); virtual const SparcInstrInfo *getInstrInfo() const {return &InstrInfo; } virtual const TargetFrameInfo *getFrameInfo() const {return &FrameInfo; } virtual const TargetSubtarget *getSubtargetImpl() const{return &Subtarget; } virtual const TargetRegisterInfo *getRegisterInfo() const { return &InstrInfo.getRegisterInfo(); } virtual const TargetData *getTargetData() const { return &DataLayout; } static unsigned getModuleMatchQuality(const Module &M); // Pass Pipeline Configuration virtual bool addInstSelector(PassManagerBase &PM, bool Fast); virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast); virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast, std::ostream &Out); }; } // end namespace llvm
For some targets, you also need to support the following methods:
In addition, the XXXTargetMachine constructor should specify a TargetDescription string that determines the data layout for the target machine, including characteristics such as pointer size, alignment, and endianness. For example, the constructor for SparcTargetMachine contains the following:
SparcTargetMachine::SparcTargetMachine(const Module &M, const std::string &FS) : DataLayout("E-p:32:32-f128:128:128"), Subtarget(M, FS), InstrInfo(Subtarget), FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) { }
Hyphens separate portions of the TargetDescription string.
You must also register your target using the RegisterTarget template. (See the TargetMachineRegistry class.) For example, in SparcTargetMachine.cpp, the target is registered with:
namespace { // Register the target. RegisterTarget<SparcTargetMachine>X("sparc", "SPARC"); }
You should describe a concrete target-specific class that represents the register file of a target machine. This class is called XXXRegisterInfo (where XXX identifies the target) and represents the class register file data that is used for register allocation and also describes the interactions between registers.
You also need to define register classes to categorize related registers. A register class should be added for groups of registers that are all treated the same way for some instruction. Typical examples are register classes that include integer, floating-point, or vector registers. A register allocator allows an instruction to use any register in a specified register class to perform the instruction in a similar manner. Register classes allocate virtual registers to instructions from these sets, and register classes let the target-independent register allocator automatically choose the actual registers.
Much of the code for registers, including register definition, register aliases, and register classes, is generated by TableGen from XXXRegisterInfo.td input files and placed in XXXGenRegisterInfo.h.inc and XXXGenRegisterInfo.inc output files. Some of the code in the implementation of XXXRegisterInfo requires hand-coding.
The XXXRegisterInfo.td file typically starts with register definitions for a target machine. The Register class (specified in Target.td) is used to define an object for each register. The specified string n becomes the Name of the register. The basic Register object does not have any subregisters and does not specify any aliases.
class Register<string n> { string Namespace = ""; string AsmName = n; string Name = n; int SpillSize = 0; int SpillAlignment = 0; list<Register> Aliases = []; list<Register> SubRegs = []; list<int> DwarfNumbers = []; }
For example, in the X86RegisterInfo.td file, there are register definitions that utilize the Register class, such as:
def AL : Register<"AL">, DwarfRegNum<[0, 0, 0]>;
This defines the register AL and assigns it values (with DwarfRegNum) that are used by gcc, gdb, or a debug information writer (such as DwarfWriter in llvm/lib/CodeGen) to identify a register. For register AL, DwarfRegNum takes an array of 3 values, representing 3 different modes: the first element is for X86-64, the second for EH (exception handling) on X86-32, and the third is generic. -1 is a special Dwarf number that indicates the gcc number is undefined, and -2 indicates the register number is invalid for this mode.
From the previously described line in the X86RegisterInfo.td file, TableGen generates this code in the X86GenRegisterInfo.inc file:
static const unsigned GR8[] = { X86::AL, ... }; const unsigned AL_AliasSet[] = { X86::AX, X86::EAX, X86::RAX, 0 }; const TargetRegisterDesc RegisterDescriptors[] = { ... { "AL", "AL", AL_AliasSet, Empty_SubRegsSet, Empty_SubRegsSet, AL_SuperRegsSet }, ...
From the register info file, TableGen generates a TargetRegisterDesc object for each register. TargetRegisterDesc is defined in include/llvm/Target/TargetRegisterInfo.h with the following fields:
struct TargetRegisterDesc { const char *AsmName; // Assembly language name for the register const char *Name; // Printable name for the reg (for debugging) const unsigned *AliasSet; // Register Alias Set const unsigned *SubRegs; // Sub-register set const unsigned *ImmSubRegs; // Immediate sub-register set const unsigned *SuperRegs; // Super-register set };
TableGen uses the entire target description file (.td) to determine text names for the register (in the AsmName and Name fields of TargetRegisterDesc) and the relationships of other registers to the defined register (in the other TargetRegisterDesc fields). In this example, other definitions establish the registers "AX", "EAX", and "RAX" as aliases for one another, so TableGen generates a null-terminated array (AL_AliasSet) for this register alias set.
The Register class is commonly used as a base class for more complex classes. In Target.td, the Register class is the base for the RegisterWithSubRegs class that is used to define registers that need to specify subregisters in the SubRegs list, as shown here:
class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> { let SubRegs = subregs; }
In SparcRegisterInfo.td, additional register classes are defined for SPARC: a Register subclass, SparcReg, and further subclasses: Ri, Rf, and Rd. SPARC registers are identified by 5-bit ID numbers, which is a feature common to these subclasses. Note the use of 'let' expressions to override values that are initially defined in a superclass (such as SubRegs field in the Rd class).
class SparcReg<string n> : Register<n> { field bits<5> Num; let Namespace = "SP"; } // Ri - 32-bit integer registers class Ri<bits<5> num, string n> : SparcReg<n> { let Num = num; } // Rf - 32-bit floating-point registers class Rf<bits<5> num, string n> : SparcReg<n> { let Num = num; } // Rd - Slots in the FP register file for 64-bit floating-point values. class Rd<bits<5> num, string n, list<Register> subregs> : SparcReg<n> { let Num = num; let SubRegs = subregs; }
In the SparcRegisterInfo.td file, there are register definitions that utilize these subclasses of Register, such as:
def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>; def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>; ... def F0 : Rf< 0, "F0">, DwarfRegNum<[32]>; def F1 : Rf< 1, "F1">, DwarfRegNum<[33]>; ... def D0 : Rd< 0, "F0", [F0, F1]>, DwarfRegNum<[32]>; def D1 : Rd< 2, "F2", [F2, F3]>, DwarfRegNum<[34]>;
The last two registers shown above (D0 and D1) are double-precision floating-point registers that are aliases for pairs of single-precision floating-point sub-registers. In addition to aliases, the sub-register and super-register relationships of the defined register are in fields of a register's TargetRegisterDesc.
The RegisterClass class (specified in Target.td) is used to define an object that represents a group of related registers and also defines the default allocation order of the registers. A target description file XXXRegisterInfo.td that uses Target.td can construct register classes using the following class:
class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, list<Register> regList> { string Namespace = namespace; list<ValueType> RegTypes = regTypes; int Size = 0; // spill size, in bits; zero lets tblgen pick the size int Alignment = alignment; // CopyCost is the cost of copying a value between two registers // default value 1 means a single instruction // A negative value means copying is extremely expensive or impossible int CopyCost = 1; list<Register> MemberList = regList; // for register classes that are subregisters of this class list<RegisterClass> SubRegClassList = []; code MethodProtos = [{}]; // to insert arbitrary code code MethodBodies = [{}]; }
To define a RegisterClass, use the following 4 arguments:
In SparcRegisterInfo.td, three RegisterClass objects are defined: FPRegs, DFPRegs, and IntRegs. For all three register classes, the first argument defines the namespace with the string "SP". FPRegs defines a group of 32 single-precision floating-point registers (F0 to F31); DFPRegs defines a group of 16 double-precision registers (D0-D15). For IntRegs, the MethodProtos and MethodBodies methods are used by TableGen to insert the specified code into generated output.
def FPRegs : RegisterClass<"SP", [f32], 32, [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>; def DFPRegs : RegisterClass<"SP", [f64], 64, [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15]>; def IntRegs : RegisterClass<"SP", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7, I0, I1, I2, I3, I4, I5, O0, O1, O2, O3, O4, O5, O7, G1, // Non-allocatable regs: G2, G3, G4, O6, // stack ptr I6, // frame ptr I7, // return address G0, // constant zero G5, G6, G7 // reserved for kernel ]> { let MethodProtos = [{ iterator allocation_order_end(const MachineFunction &MF) const; }]; let MethodBodies = [{ IntRegsClass::iterator IntRegsClass::allocation_order_end(const MachineFunction &MF) const { return end()-10 // Don't allocate special registers -1; } }]; }
Using SparcRegisterInfo.td with TableGen generates several output files that are intended for inclusion in other source code that you write. SparcRegisterInfo.td generates SparcGenRegisterInfo.h.inc, which should be included in the header file for the implementation of the SPARC register implementation that you write (SparcRegisterInfo.h). In SparcGenRegisterInfo.h.inc a new structure is defined called SparcGenRegisterInfo that uses TargetRegisterInfo as its base. It also specifies types, based upon the defined register classes: DFPRegsClass, FPRegsClass, and IntRegsClass.
SparcRegisterInfo.td also generates SparcGenRegisterInfo.inc, which is included at the bottom of SparcRegisterInfo.cpp, the SPARC register implementation. The code below shows only the generated integer registers and associated register classes. The order of registers in IntRegs reflects the order in the definition of IntRegs in the target description file. Take special note of the use of MethodBodies in SparcRegisterInfo.td to create code in SparcGenRegisterInfo.inc. MethodProtos generates similar code in SparcGenRegisterInfo.h.inc.
// IntRegs Register Class... static const unsigned IntRegs[] = { SP::L0, SP::L1, SP::L2, SP::L3, SP::L4, SP::L5, SP::L6, SP::L7, SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5, SP::O0, SP::O1, SP::O2, SP::O3, SP::O4, SP::O5, SP::O7, SP::G1, SP::G2, SP::G3, SP::G4, SP::O6, SP::I6, SP::I7, SP::G0, SP::G5, SP::G6, SP::G7, }; // IntRegsVTs Register Class Value Types... static const MVT::ValueType IntRegsVTs[] = { MVT::i32, MVT::Other }; namespace SP { // Register class instances DFPRegsClass DFPRegsRegClass; FPRegsClass FPRegsRegClass; IntRegsClass IntRegsRegClass; ... // IntRegs Sub-register Classess... static const TargetRegisterClass* const IntRegsSubRegClasses [] = { NULL }; ... // IntRegs Super-register Classess... static const TargetRegisterClass* const IntRegsSuperRegClasses [] = { NULL }; // IntRegs Register Class sub-classes... static const TargetRegisterClass* const IntRegsSubclasses [] = { NULL }; ... // IntRegs Register Class super-classes... static const TargetRegisterClass* const IntRegsSuperclasses [] = { NULL }; ... IntRegsClass::iterator IntRegsClass::allocation_order_end(const MachineFunction &MF) const { return end()-10 // Don't allocate special registers -1; } IntRegsClass::IntRegsClass() : TargetRegisterClass(IntRegsRegClassID, IntRegsVTs, IntRegsSubclasses, IntRegsSuperclasses, IntRegsSubRegClasses, IntRegsSuperRegClasses, 4, 4, 1, IntRegs, IntRegs + 32) {} }
The final step is to hand code portions of XXXRegisterInfo, which implements the interface described in TargetRegisterInfo.h. These functions return 0, NULL, or false, unless overridden. Here's a list of functions that are overridden for the SPARC implementation in SparcRegisterInfo.cpp:
During the early stages of code generation, the LLVM IR code is converted to a SelectionDAG with nodes that are instances of the SDNode class containing target instructions. An SDNode has an opcode, operands, type requirements, and operation properties (for example, is an operation commutative, does an operation load from memory). The various operation node types are described in the include/llvm/CodeGen/SelectionDAGNodes.h file (values of the NodeType enum in the ISD namespace).
TableGen uses the following target description (.td) input files to generate much of the code for instruction definition:
There is also a target-specific XXX.td file, where XXX is the name of the target. The XXX.td file includes the other .td input files, but its contents are only directly important for subtargets.
You should describe a concrete target-specific class XXXInstrInfo that represents machine instructions supported by a target machine. XXXInstrInfo contains an array of XXXInstrDescriptor objects, each of which describes one instruction. An instruction descriptor defines:
The Instruction class (defined in Target.td) is mostly used as a base for more complex instruction classes.
class Instruction { string Namespace = ""; dag OutOperandList; // An dag containing the MI def operand list. dag InOperandList; // An dag containing the MI use operand list. string AsmString = ""; // The .s format to print the instruction with. list<dag> Pattern; // Set to the DAG pattern for this instruction list<Register> Uses = []; list<Register> Defs = []; list<Predicate> Predicates = []; // predicates turned into isel match code ... remainder not shown for space ... }
A SelectionDAG node (SDNode) should contain an object representing a target-specific instruction that is defined in XXXInstrInfo.td. The instruction objects should represent instructions from the architecture manual of the target machine (such as the SPARC Architecture Manual for the SPARC target).
A single instruction from the architecture manual is often modeled as multiple target instructions, depending upon its operands. For example, a manual might describe an add instruction that takes a register or an immediate operand. An LLVM target could model this with two instructions named ADDri and ADDrr.
You should define a class for each instruction category and define each opcode as a subclass of the category with appropriate parameters such as the fixed binary encoding of opcodes and extended opcodes. You should map the register bits to the bits of the instruction in which they are encoded (for the JIT). Also you should specify how the instruction should be printed when the automatic assembly printer is used.
As is described in the SPARC Architecture Manual, Version 8, there are three major 32-bit formats for instructions. Format 1 is only for the CALL instruction. Format 2 is for branch on condition codes and SETHI (set high bits of a register) instructions. Format 3 is for other instructions.
Each of these formats has corresponding classes in SparcInstrFormat.td. InstSP is a base class for other instruction classes. Additional base classes are specified for more precise formats: for example in SparcInstrFormat.td, F2_1 is for SETHI, and F2_2 is for branches. There are three other base classes: F3_1 for register/register operations, F3_2 for register/immediate operations, and F3_3 for floating-point operations. SparcInstrInfo.td also adds the base class Pseudo for synthetic SPARC instructions.
SparcInstrInfo.td largely consists of operand and instruction definitions for the SPARC target. In SparcInstrInfo.td, the following target description file entry, LDrr, defines the Load Integer instruction for a Word (the LD SPARC opcode) from a memory address to a register. The first parameter, the value 3 (112), is the operation value for this category of operation. The second parameter (0000002) is the specific operation value for LD/Load Word. The third parameter is the output destination, which is a register operand and defined in the Register target description file (IntRegs).
def LDrr : F3_1 <3, 0b000000, (outs IntRegs:$dst), (ins MEMrr:$addr), "ld [$addr], $dst", [(set IntRegs:$dst, (load ADDRrr:$addr))]>;
The fourth parameter is the input source, which uses the address operand MEMrr that is defined earlier in SparcInstrInfo.td:
def MEMrr : Operand<i32> { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops IntRegs, IntRegs); }
The fifth parameter is a string that is used by the assembly printer and can be left as an empty string until the assembly printer interface is implemented. The sixth and final parameter is the pattern used to match the instruction during the SelectionDAG Select Phase described in (The LLVM Target-Independent Code Generator). This parameter is detailed in the next section, Instruction Selector.
Instruction class definitions are not overloaded for different operand types, so separate versions of instructions are needed for register, memory, or immediate value operands. For example, to perform a Load Integer instruction for a Word from an immediate operand to a register, the following instruction class is defined:
def LDri : F3_2 <3, 0b000000, (outs IntRegs:$dst), (ins MEMri:$addr), "ld [$addr], $dst", [(set IntRegs:$dst, (load ADDRri:$addr))]>;
Writing these definitions for so many similar instructions can involve a lot of cut and paste. In td files, the multiclass directive enables the creation of templates to define several instruction classes at once (using the defm directive). For example in SparcInstrInfo.td, the multiclass pattern F3_12 is defined to create 2 instruction classes each time F3_12 is invoked:
multiclass F3_12 <string OpcStr, bits<6> Op3Val, SDNode OpNode> { def rr : F3_1 <2, Op3Val, (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), !strconcat(OpcStr, " $b, $c, $dst"), [(set IntRegs:$dst, (OpNode IntRegs:$b, IntRegs:$c))]>; def ri : F3_2 <2, Op3Val, (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), !strconcat(OpcStr, " $b, $c, $dst"), [(set IntRegs:$dst, (OpNode IntRegs:$b, simm13:$c))]>; }
So when the defm directive is used for the XOR and ADD instructions, as seen below, it creates four instruction objects: XORrr, XORri, ADDrr, and ADDri.
defm XOR : F3_12<"xor", 0b000011, xor>; defm ADD : F3_12<"add", 0b000000, add>;
SparcInstrInfo.td also includes definitions for condition codes that are referenced by branch instructions. The following definitions in SparcInstrInfo.td indicate the bit location of the SPARC condition code; for example, the 10th bit represents the 'greater than' condition for integers, and the 22nd bit represents the 'greater than' condition for floats.
def ICC_NE : ICC_VAL< 9>; // Not Equal def ICC_E : ICC_VAL< 1>; // Equal def ICC_G : ICC_VAL<10>; // Greater ... def FCC_U : FCC_VAL<23>; // Unordered def FCC_G : FCC_VAL<22>; // Greater def FCC_UG : FCC_VAL<21>; // Unordered or Greater ...
(Note that Sparc.h also defines enums that correspond to the same SPARC condition codes. Care must be taken to ensure the values in Sparc.h correspond to the values in SparcInstrInfo.td; that is, SPCC::ICC_NE = 9, SPCC::FCC_U = 23 and so on.)
The code generator backend maps instruction operands to fields in the instruction. Operands are assigned to unbound fields in the instruction in the order they are defined. Fields are bound when they are assigned a value. For example, the Sparc target defines the XNORrr instruction as a F3_1 format instruction having three operands.
def XNORrr : F3_1<2, 0b000111, (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), "xnor $b, $c, $dst", [(set IntRegs:$dst, (not (xor IntRegs:$b, IntRegs:$c)))]>;
The instruction templates in SparcInstrFormats.td show the base class for F3_1 is InstSP.
class InstSP<dag outs, dag ins, string asmstr, list<dag> pattern> : Instruction { field bits<32> Inst; let Namespace = "SP"; bits<2> op; let Inst{31-30} = op; dag OutOperandList = outs; dag InOperandList = ins; let AsmString = asmstr; let Pattern = pattern; }
InstSP leaves the op field unbound.
class F3<dag outs, dag ins, string asmstr, list<dag> pattern> : InstSP<outs, ins, asmstr, pattern> { bits<5> rd; bits<6> op3; bits<5> rs1; let op{1} = 1; // Op = 2 or 3 let Inst{29-25} = rd; let Inst{24-19} = op3; let Inst{18-14} = rs1; }
F3 binds the op field and defines the rd, op3, and rs1 fields. F3 format instructions will bind the operands rd, op3, and rs1 fields.
class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins, string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> { bits<8> asi = 0; // asi not currently used bits<5> rs2; let op = opVal; let op3 = op3val; let Inst{13} = 0; // i field = 0 let Inst{12-5} = asi; // address space identifier let Inst{4-0} = rs2; }
F3_1 binds the op3 field and defines the rs2 fields. F3_1 format instructions will bind the operands to the rd, rs1, and rs2 fields. This results in the XNORrr instruction binding $dst, $b, and $c operands to the rd, rs1, and rs2 fields respectively.
The final step is to hand code portions of XXXInstrInfo, which implements the interface described in TargetInstrInfo.h. These functions return 0 or a Boolean or they assert, unless overridden. Here's a list of functions that are overridden for the SPARC implementation in SparcInstrInfo.cpp:
Performance can be improved by combining instructions or by eliminating instructions that are never reached. The AnalyzeBranch method in XXXInstrInfo may be implemented to examine conditional instructions and remove unnecessary instructions. AnalyzeBranch looks at the end of a machine basic block (MBB) for opportunities for improvement, such as branch folding and if conversion. The BranchFolder and IfConverter machine function passes (see the source files BranchFolding.cpp and IfConversion.cpp in the lib/CodeGen directory) call AnalyzeBranch to improve the control flow graph that represents the instructions.
Several implementations of AnalyzeBranch (for ARM, Alpha, and X86) can be examined as models for your own AnalyzeBranch implementation. Since SPARC does not implement a useful AnalyzeBranch, the ARM target implementation is shown below.
AnalyzeBranch returns a Boolean value and takes four parameters:
In the simplest case, if a block ends without a branch, then it falls through to the successor block. No destination blocks are specified for either TBB or FBB, so both parameters return NULL. The start of the AnalyzeBranch (see code below for the ARM target) shows the function parameters and the code for the simplest case.
bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, std::vector<MachineOperand> &Cond) const { MachineBasicBlock::iterator I = MBB.end(); if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) return false;
If a block ends with a single unconditional branch instruction, then AnalyzeBranch (shown below) should return the destination of that branch in the TBB parameter.
if (LastOpc == ARM::B || LastOpc == ARM::tB) { TBB = LastInst->getOperand(0).getMBB(); return false; }
If a block ends with two unconditional branches, then the second branch is never reached. In that situation, as shown below, remove the last branch instruction and return the penultimate branch in the TBB parameter.
if ((SecondLastOpc == ARM::B || SecondLastOpc==ARM::tB) && (LastOpc == ARM::B || LastOpc == ARM::tB)) { TBB = SecondLastInst->getOperand(0).getMBB(); I = LastInst; I->eraseFromParent(); return false; }
A block may end with a single conditional branch instruction that falls through to successor block if the condition evaluates to false. In that case, AnalyzeBranch (shown below) should return the destination of that conditional branch in the TBB parameter and a list of operands in the Cond parameter to evaluate the condition.
if (LastOpc == ARM::Bcc || LastOpc == ARM::tBcc) { // Block ends with fall-through condbranch. TBB = LastInst->getOperand(0).getMBB(); Cond.push_back(LastInst->getOperand(1)); Cond.push_back(LastInst->getOperand(2)); return false; }
If a block ends with both a conditional branch and an ensuing unconditional branch, then AnalyzeBranch (shown below) should return the conditional branch destination (assuming it corresponds to a conditional evaluation of 'true') in the TBB parameter and the unconditional branch destination in the FBB (corresponding to a conditional evaluation of 'false'). A list of operands to evaluate the condition should be returned in the Cond parameter.
unsigned SecondLastOpc = SecondLastInst->getOpcode(); if ((SecondLastOpc == ARM::Bcc && LastOpc == ARM::B) || (SecondLastOpc == ARM::tBcc && LastOpc == ARM::tB)) { TBB = SecondLastInst->getOperand(0).getMBB(); Cond.push_back(SecondLastInst->getOperand(1)); Cond.push_back(SecondLastInst->getOperand(2)); FBB = LastInst->getOperand(0).getMBB(); return false; }
For the last two cases (ending with a single conditional branch or ending with one conditional and one unconditional branch), the operands returned in the Cond parameter can be passed to methods of other instructions to create new branches or perform other operations. An implementation of AnalyzeBranch requires the helper methods RemoveBranch and InsertBranch to manage subsequent operations.
AnalyzeBranch should return false indicating success in most circumstances. AnalyzeBranch should only return true when the method is stumped about what to do, for example, if a block has three terminating branches. AnalyzeBranch may return true if it encounters a terminator it cannot handle, such as an indirect branch.
LLVM uses a SelectionDAG to represent LLVM IR instructions, and nodes of the SelectionDAG ideally represent native target instructions. During code generation, instruction selection passes are performed to convert non-native DAG instructions into native target-specific instructions. The pass described in XXXISelDAGToDAG.cpp is used to match patterns and perform DAG-to-DAG instruction selection. Optionally, a pass may be defined (in XXXBranchSelector.cpp) to perform similar DAG-to-DAG operations for branch instructions. Later, the code in XXXISelLowering.cpp replaces or removes operations and data types not supported natively (legalizes) in a Selection DAG.
TableGen generates code for instruction selection using the following target description input files:
The implementation of an instruction selection pass must include a header that declares the FunctionPass class or a subclass of FunctionPass. In XXXTargetMachine.cpp, a Pass Manager (PM) should add each instruction selection pass into the queue of passes to run.
The LLVM static compiler (llc) is an excellent tool for visualizing the contents of DAGs. To display the SelectionDAG before or after specific processing phases, use the command line options for llc, described at SelectionDAG Instruction Selection Process.
To describe instruction selector behavior, you should add patterns for lowering LLVM code into a SelectionDAG as the last parameter of the instruction definitions in XXXInstrInfo.td. For example, in SparcInstrInfo.td, this entry defines a register store operation, and the last parameter describes a pattern with the store DAG operator.
def STrr : F3_1< 3, 0b000100, (outs), (ins MEMrr:$addr, IntRegs:$src), "st $src, [$addr]", [(store IntRegs:$src, ADDRrr:$addr)]>;
ADDRrr is a memory mode that is also defined in SparcInstrInfo.td:
def ADDRrr : ComplexPattern<i32, 2, "SelectADDRrr", [], []>;
The definition of ADDRrr refers to SelectADDRrr, which is a function defined in an implementation of the Instructor Selector (such as SparcISelDAGToDAG.cpp).
In lib/Target/TargetSelectionDAG.td, the DAG operator for store is defined below:
def store : PatFrag<(ops node:$val, node:$ptr), (st node:$val, node:$ptr), [{ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) return !ST->isTruncatingStore() && ST->getAddressingMode() == ISD::UNINDEXED; return false; }]>;
XXXInstrInfo.td also generates (in XXXGenDAGISel.inc) the SelectCode method that is used to call the appropriate processing method for an instruction. In this example, SelectCode calls Select_ISD_STORE for the ISD::STORE opcode.
SDNode *SelectCode(SDValue N) { ... MVT::ValueType NVT = N.getNode()->getValueType(0); switch (N.getOpcode()) { case ISD::STORE: { switch (NVT) { default: return Select_ISD_STORE(N); break; } break; } ...
The pattern for STrr is matched, so elsewhere in XXXGenDAGISel.inc, code for STrr is created for Select_ISD_STORE. The Emit_22 method is also generated in XXXGenDAGISel.inc to complete the processing of this instruction.
SDNode *Select_ISD_STORE(const SDValue &N) { SDValue Chain = N.getOperand(0); if (Predicate_store(N.getNode())) { SDValue N1 = N.getOperand(1); SDValue N2 = N.getOperand(2); SDValue CPTmp0; SDValue CPTmp1; // Pattern: (st:void IntRegs:i32:$src, // ADDRrr:i32:$addr)<<P:Predicate_store>> // Emits: (STrr:void ADDRrr:i32:$addr, IntRegs:i32:$src) // Pattern complexity = 13 cost = 1 size = 0 if (SelectADDRrr(N, N2, CPTmp0, CPTmp1) && N1.getNode()->getValueType(0) == MVT::i32 && N2.getNode()->getValueType(0) == MVT::i32) { return Emit_22(N, SP::STrr, CPTmp0, CPTmp1); } ...
The Legalize phase converts a DAG to use types and operations that are natively supported by the target. For natively unsupported types and operations, you need to add code to the target-specific XXXTargetLowering implementation to convert unsupported types and operations to supported ones.
In the constructor for the XXXTargetLowering class, first use the addRegisterClass method to specify which types are supports and which register classes are associated with them. The code for the register classes are generated by TableGen from XXXRegisterInfo.td and placed in XXXGenRegisterInfo.h.inc. For example, the implementation of the constructor for the SparcTargetLowering class (in SparcISelLowering.cpp) starts with the following code:
addRegisterClass(MVT::i32, SP::IntRegsRegisterClass); addRegisterClass(MVT::f32, SP::FPRegsRegisterClass); addRegisterClass(MVT::f64, SP::DFPRegsRegisterClass);
You should examine the node types in the ISD namespace (include/llvm/CodeGen/SelectionDAGNodes.h) and determine which operations the target natively supports. For operations that do not have native support, add a callback to the constructor for the XXXTargetLowering class, so the instruction selection process knows what to do. The TargetLowering class callback methods (declared in llvm/Target/TargetLowering.h) are:
Note: on older releases, setLoadXAction is used instead of setLoadExtAction. Also, on older releases, setCondCodeAction may not be supported. Examine your release to see what methods are specifically supported.
These callbacks are used to determine that an operation does or does not work with a specified type (or types). And in all cases, the third parameter is a LegalAction type enum value: Promote, Expand, Custom, or Legal. SparcISelLowering.cpp contains examples of all four LegalAction values.
For an operation without native support for a given type, the specified type may be promoted to a larger type that is supported. For example, SPARC does not support a sign-extending load for Boolean values (i1 type), so in SparcISelLowering.cpp the third parameter below, Promote, changes i1 type values to a large type before loading.
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
For a type without native support, a value may need to be broken down further, rather than promoted. For an operation without native support, a combination of other operations may be used to similar effect. In SPARC, the floating-point sine and cosine trig operations are supported by expansion to other operations, as indicated by the third parameter, Expand, to setOperationAction:
setOperationAction(ISD::FSIN, MVT::f32, Expand); setOperationAction(ISD::FCOS, MVT::f32, Expand);
For some operations, simple type promotion or operation expansion may be insufficient. In some cases, a special intrinsic function must be implemented.
For example, a constant value may require special treatment, or an operation may require spilling and restoring registers in the stack and working with register allocators.
As seen in SparcISelLowering.cpp code below, to perform a type conversion from a floating point value to a signed integer, first the setOperationAction should be called with Custom as the third parameter:
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
In the LowerOperation method, for each Custom operation, a case statement should be added to indicate what function to call. In the following code, an FP_TO_SINT opcode will call the LowerFP_TO_SINT method:
SDValue SparcTargetLowering::LowerOperation( SDValue Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG); ... } }
Finally, the LowerFP_TO_SINT method is implemented, using an FP register to convert the floating-point value to an integer.
static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { assert(Op.getValueType() == MVT::i32); Op = DAG.getNode(SPISD::FTOI, MVT::f32, Op.getOperand(0)); return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Op); }
The Legal LegalizeAction enum value simply indicates that an operation is natively supported. Legal represents the default condition, so it is rarely used. In SparcISelLowering.cpp, the action for CTPOP (an operation to count the bits set in an integer) is natively supported only for SPARC v9. The following code enables the Expand conversion technique for non-v9 SPARC implementations.
setOperationAction(ISD::CTPOP, MVT::i32, Expand); ... if (TM.getSubtarget<SparcSubtarget>().isV9()) setOperationAction(ISD::CTPOP, MVT::i32, Legal); case ISD::SETULT: return SPCC::ICC_CS; case ISD::SETULE: return SPCC::ICC_LEU; case ISD::SETUGT: return SPCC::ICC_GU; case ISD::SETUGE: return SPCC::ICC_CC; } }
To support target-specific calling conventions, XXXGenCallingConv.td uses interfaces (such as CCIfType and CCAssignToReg) that are defined in lib/Target/TargetCallingConv.td. TableGen can take the target descriptor file XXXGenCallingConv.td and generate the header file XXXGenCallingConv.inc, which is typically included in XXXISelLowering.cpp. You can use the interfaces in TargetCallingConv.td to specify:
The following example demonstrates the use of the CCIfType and CCAssignToReg interfaces. If the CCIfType predicate is true (that is, if the current argument is of type f32 or f64), then the action is performed. In this case, the CCAssignToReg action assigns the argument value to the first available register: either R0 or R1.
CCIfType<[f32,f64], CCAssignToReg<[R0, R1]>>
SparcCallingConv.td contains definitions for a target-specific return-value calling convention (RetCC_Sparc32) and a basic 32-bit C calling convention (CC_Sparc32). The definition of RetCC_Sparc32 (shown below) indicates which registers are used for specified scalar return types. A single-precision float is returned to register F0, and a double-precision float goes to register D0. A 32-bit integer is returned in register I0 or I1.
def RetCC_Sparc32 : CallingConv<[ CCIfType<[i32], CCAssignToReg<[I0, I1]>>, CCIfType<[f32], CCAssignToReg<[F0]>>, CCIfType<[f64], CCAssignToReg<[D0]>> ]>;
The definition of CC_Sparc32 in SparcCallingConv.td introduces CCAssignToStack, which assigns the value to a stack slot with the specified size and alignment. In the example below, the first parameter, 4, indicates the size of the slot, and the second parameter, also 4, indicates the stack alignment along 4-byte units. (Special cases: if size is zero, then the ABI size is used; if alignment is zero, then the ABI alignment is used.)
def CC_Sparc32 : CallingConv<[ // All arguments get passed in integer registers if there is space. CCIfType<[i32, f32, f64], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, CCAssignToStack<4, 4> ]>;
CCDelegateTo is another commonly used interface, which tries to find a specified sub-calling convention and, if a match is found, it is invoked. In the following example (in X86CallingConv.td), the definition of RetCC_X86_32_C ends with CCDelegateTo. After the current value is assigned to the register ST0 or ST1, the RetCC_X86Common is invoked.
def RetCC_X86_32_C : CallingConv<[ CCIfType<[f32], CCAssignToReg<[ST0, ST1]>>, CCIfType<[f64], CCAssignToReg<[ST0, ST1]>>, CCDelegateTo<RetCC_X86Common> ]>;
CCIfCC is an interface that attempts to match the given name to the current calling convention. If the name identifies the current calling convention, then a specified action is invoked. In the following example (in X86CallingConv.td), if the Fast calling convention is in use, then RetCC_X86_32_Fast is invoked. If the SSECall calling convention is in use, then RetCC_X86_32_SSE is invoked.
def RetCC_X86_32 : CallingConv<[ CCIfCC<"CallingConv::Fast", CCDelegateTo<RetCC_X86_32_Fast>>, CCIfCC<"CallingConv::X86_SSECall", CCDelegateTo<RetCC_X86_32_SSE>>, CCDelegateTo<RetCC_X86_32_C> ]>;
Other calling convention interfaces include:
During the code emission stage, the code generator may utilize an LLVM pass to produce assembly output. To do this, you want to implement the code for a printer that converts LLVM IR to a GAS-format assembly language for your target machine, using the following steps:
The code in XXXTargetAsmInfo.h is usually a trivial declaration of the XXXTargetAsmInfo class for use in XXXTargetAsmInfo.cpp. Similarly, XXXTargetAsmInfo.cpp usually has a few declarations of XXXTargetAsmInfo replacement values that override the default values in TargetAsmInfo.cpp. For example in SparcTargetAsmInfo.cpp,
SparcTargetAsmInfo::SparcTargetAsmInfo(const SparcTargetMachine &TM) { Data16bitsDirective = "\t.half\t"; Data32bitsDirective = "\t.word\t"; Data64bitsDirective = 0; // .xword is only supported by V9. ZeroDirective = "\t.skip\t"; CommentString = "!"; ConstantPoolSection = "\t.section \".rodata\",#alloc\n"; }
The X86 assembly printer implementation (X86TargetAsmInfo) is an example where the target specific TargetAsmInfo class uses overridden methods: ExpandInlineAsm and PreferredEHDataFormat.
A target-specific implementation of AsmPrinter is written in XXXAsmPrinter.cpp, which implements the AsmPrinter class that converts the LLVM to printable assembly. The implementation must include the following headers that have declarations for the AsmPrinter and MachineFunctionPass classes. The MachineFunctionPass is a subclass of FunctionPass.
#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineFunctionPass.h"
As a FunctionPass, AsmPrinter first calls doInitialization to set up the AsmPrinter. In SparcAsmPrinter, a Mangler object is instantiated to process variable names.
In XXXAsmPrinter.cpp, the runOnMachineFunction method (declared in MachineFunctionPass) must be implemented for XXXAsmPrinter. In MachineFunctionPass, the runOnFunction method invokes runOnMachineFunction. Target-specific implementations of runOnMachineFunction differ, but generally do the following to process each machine function:
The XXXAsmPrinter implementation must also include the code generated by TableGen that is output in the XXXGenAsmWriter.inc file. The code in XXXGenAsmWriter.inc contains an implementation of the printInstruction method that may call these methods:
The implementations of printDeclare, printImplicitDef, printInlineAsm, and printLabel in AsmPrinter.cpp are generally adequate for printing assembly and do not need to be overridden. (printBasicBlockLabel is another method that is implemented in AsmPrinter.cpp that may be directly used in an implementation of XXXAsmPrinter.)
The printOperand method is implemented with a long switch/case statement for the type of operand: register, immediate, basic block, external symbol, global address, constant pool index, or jump table index. For an instruction with a memory address operand, the printMemOperand method should be implemented to generate the proper output. Similarly, printCCOperand should be used to print a conditional operand.
doFinalization should be overridden in XXXAsmPrinter, and it should be called to shut down the assembly printer. During doFinalization, global variables and constants are printed to output.
Subtarget support is used to inform the code generation process of instruction set variations for a given chip set. For example, the LLVM SPARC implementation provided covers three major versions of the SPARC microprocessor architecture: Version 8 (V8, which is a 32-bit architecture), Version 9 (V9, a 64-bit architecture), and the UltraSPARC architecture. V8 has 16 double-precision floating-point registers that are also usable as either 32 single-precision or 8 quad-precision registers. V8 is also purely big-endian. V9 has 32 double-precision floating-point registers that are also usable as 16 quad-precision registers, but cannot be used as single-precision registers. The UltraSPARC architecture combines V9 with UltraSPARC Visual Instruction Set extensions.
If subtarget support is needed, you should implement a target-specific XXXSubtarget class for your architecture. This class should process the command-line options –mcpu= and –mattr=
TableGen uses definitions in the Target.td and Sparc.td files to generate code in SparcGenSubtarget.inc. In Target.td, shown below, the SubtargetFeature interface is defined. The first 4 string parameters of the SubtargetFeature interface are a feature name, an attribute set by the feature, the value of the attribute, and a description of the feature. (The fifth parameter is a list of features whose presence is implied, and its default value is an empty array.)
class SubtargetFeature<string n, string a, string v, string d, list<SubtargetFeature> i = []> { string Name = n; string Attribute = a; string Value = v; string Desc = d; list<SubtargetFeature> Implies = i; }
In the Sparc.td file, the SubtargetFeature is used to define the following features.
def FeatureV9 : SubtargetFeature<"v9", "IsV9", "true", "Enable SPARC-V9 instructions">; def FeatureV8Deprecated : SubtargetFeature<"deprecated-v8", "V8DeprecatedInsts", "true", "Enable deprecated V8 instructions in V9 mode">; def FeatureVIS : SubtargetFeature<"vis", "IsVIS", "true", "Enable UltraSPARC Visual Instruction Set extensions">;
Elsewhere in Sparc.td, the Proc class is defined and then is used to define particular SPARC processor subtypes that may have the previously described features.
class Proc<string Name, list<SubtargetFeature> Features> : Processor<Name, NoItineraries, Features>; def : Proc<"generic", []>; def : Proc<"v8", []>; def : Proc<"supersparc", []>; def : Proc<"sparclite", []>; def : Proc<"f934", []>; def : Proc<"hypersparc", []>; def : Proc<"sparclite86x", []>; def : Proc<"sparclet", []>; def : Proc<"tsc701", []>; def : Proc<"v9", [FeatureV9]>; def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated]>; def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>; def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
From Target.td and Sparc.td files, the resulting SparcGenSubtarget.inc specifies enum values to identify the features, arrays of constants to represent the CPU features and CPU subtypes, and the ParseSubtargetFeatures method that parses the features string that sets specified subtarget options. The generated SparcGenSubtarget.inc file should be included in the SparcSubtarget.cpp. The target-specific implementation of the XXXSubtarget method should follow this pseudocode:
XXXSubtarget::XXXSubtarget(const Module &M, const std::string &FS) { // Set the default features // Determine default and user specified characteristics of the CPU // Call ParseSubtargetFeatures(FS, CPU) to parse the features string // Perform any additional operations }
The implementation of a target machine optionally includes a Just-In-Time (JIT) code generator that emits machine code and auxiliary structures as binary output that can be written directly to memory. To do this, implement JIT code generation by performing the following steps:
There are several different approaches to writing the JIT support code. For instance, TableGen and target descriptor files may be used for creating a JIT code generator, but are not mandatory. For the Alpha and PowerPC target machines, TableGen is used to generate XXXGenCodeEmitter.inc, which contains the binary coding of machine instructions and the getBinaryCodeForInstr method to access those codes. Other JIT implementations do not.
Both XXXJITInfo.cpp and XXXCodeEmitter.cpp must include the llvm/CodeGen/MachineCodeEmitter.h header file that defines the MachineCodeEmitter class containing code for several callback functions that write data (in bytes, words, strings, etc.) to the output stream.
In XXXCodeEmitter.cpp, a target-specific of the Emitter class is implemented as a function pass (subclass of MachineFunctionPass). The target-specific implementation of runOnMachineFunction (invoked by runOnFunction in MachineFunctionPass) iterates through the MachineBasicBlock calls emitInstruction to process each instruction and emit binary code. emitInstruction is largely implemented with case statements on the instruction types defined in XXXInstrInfo.h. For example, in X86CodeEmitter.cpp, the emitInstruction method is built around the following switch/case statements:
switch (Desc->TSFlags & X86::FormMask) { case X86II::Pseudo: // for not yet implemented instructions ... // or pseudo-instructions break; case X86II::RawFrm: // for instructions with a fixed opcode value ... break; case X86II::AddRegFrm: // for instructions that have one register operand ... // added to their opcode break; case X86II::MRMDestReg:// for instructions that use the Mod/RM byte ... // to specify a destination (register) break; case X86II::MRMDestMem:// for instructions that use the Mod/RM byte ... // to specify a destination (memory) break; case X86II::MRMSrcReg: // for instructions that use the Mod/RM byte ... // to specify a source (register) break; case X86II::MRMSrcMem: // for instructions that use the Mod/RM byte ... // to specify a source (memory) break; case X86II::MRM0r: case X86II::MRM1r: // for instructions that operate on case X86II::MRM2r: case X86II::MRM3r: // a REGISTER r/m operand and case X86II::MRM4r: case X86II::MRM5r: // use the Mod/RM byte and a field case X86II::MRM6r: case X86II::MRM7r: // to hold extended opcode data ... break; case X86II::MRM0m: case X86II::MRM1m: // for instructions that operate on case X86II::MRM2m: case X86II::MRM3m: // a MEMORY r/m operand and case X86II::MRM4m: case X86II::MRM5m: // use the Mod/RM byte and a field case X86II::MRM6m: case X86II::MRM7m: // to hold extended opcode data ... break; case X86II::MRMInitReg: // for instructions whose source and ... // destination are the same register break; }
The implementations of these case statements often first emit the opcode and then get the operand(s). Then depending upon the operand, helper methods may be called to process the operand(s). For example, in X86CodeEmitter.cpp, for the X86II::AddRegFrm case, the first data emitted (by emitByte) is the opcode added to the register operand. Then an object representing the machine operand, MO1, is extracted. The helper methods such as isImmediate, isGlobalAddress, isExternalSymbol, isConstantPoolIndex, and isJumpTableIndex determine the operand type. (X86CodeEmitter.cpp also has private methods such as emitConstant, emitGlobalAddress, emitExternalSymbolAddress, emitConstPoolAddress, and emitJumpTableAddress that emit the data into the output stream.)
case X86II::AddRegFrm: MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++).getReg())); if (CurOp != NumOps) { const MachineOperand &MO1 = MI.getOperand(CurOp++); unsigned Size = X86InstrInfo::sizeOfImm(Desc); if (MO1.isImmediate()) emitConstant(MO1.getImm(), Size); else { unsigned rt = Is64BitMode ? X86::reloc_pcrel_word : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); if (Opcode == X86::MOV64ri) rt = X86::reloc_absolute_dword; // FIXME: add X86II flag? if (MO1.isGlobalAddress()) { bool NeedStub = isa<Function>(MO1.getGlobal()); bool isLazy = gvNeedsLazyPtr(MO1.getGlobal()); emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, NeedStub, isLazy); } else if (MO1.isExternalSymbol()) emitExternalSymbolAddress(MO1.getSymbolName(), rt); else if (MO1.isConstantPoolIndex()) emitConstPoolAddress(MO1.getIndex(), rt); else if (MO1.isJumpTableIndex()) emitJumpTableAddress(MO1.getIndex(), rt); } } break;
In the previous example, XXXCodeEmitter.cpp uses the variable rt, which is a RelocationType enum that may be used to relocate addresses (for example, a global address with a PIC base offset). The RelocationType enum for that target is defined in the short target-specific XXXRelocations.h file. The RelocationType is used by the relocate method defined in XXXJITInfo.cpp to rewrite addresses for referenced global symbols.
For example, X86Relocations.h specifies the following relocation types for the X86 addresses. In all four cases, the relocated value is added to the value already in memory. For reloc_pcrel_word and reloc_picrel_word, there is an additional initial adjustment.
enum RelocationType { reloc_pcrel_word = 0, // add reloc value after adjusting for the PC loc reloc_picrel_word = 1, // add reloc value after adjusting for the PIC base reloc_absolute_word = 2, // absolute relocation; no additional adjustment reloc_absolute_dword = 3 // absolute relocation; no additional adjustment };
XXXJITInfo.cpp implements the JIT interfaces for target-specific code-generation activities, such as emitting machine code and stubs. At minimum, a target-specific version of XXXJITInfo implements the following:
getLazyResolverFunction is generally trivial to implement. It makes the incoming parameter as the global JITCompilerFunction and returns the callback function that will be used a function wrapper. For the Alpha target (in AlphaJITInfo.cpp), the getLazyResolverFunction implementation is simply:
TargetJITInfo::LazyResolverFn AlphaJITInfo::getLazyResolverFunction( JITCompilerFn F) { JITCompilerFunction = F; return AlphaCompilationCallback; }
For the X86 target, the getLazyResolverFunction implementation is a little more complication, because it returns a different callback function for processors with SSE instructions and XMM registers.
The callback function initially saves and later restores the callee register values, incoming arguments, and frame and return address. The callback function needs low-level access to the registers or stack, so it is typically implemented with assembler.


text:
Lucille Tenazas is both an educator and graphic designer. Her studio, Tenazas Design was based in San Francisco for 20 years but relocated to New York in 2006, returning to the city where she originally began her practice in 1982. She is the Henry Wolf Professor in the School of Art, Media and Technology at Parsons The New School for Design where she is developing a graduate concentration in Design, Craft and Technology. Previously, she was the Founding Chair of the MFA program in Design at California College of the Arts in San Francisco.
Lucille's work has been featured in many publications and exhibitions both nationally and internationally, including a 2003 retrospective of her work from the permanent collection of the San Francisco Museum of Modern Art. Among her clients have been the San Francisco International Airport, Princeton Architectural Press, Rizzoli International, Neue Galerie Museum for German and Austrian Art and projects for numerous non-profit organizations and institutions.From 1996 to 1998, she was the national president of the AIGA and is currently on the board of the AIGA/NY chapter involved in education initiatives. In 2002, she received the National Design Award for Communication Design from the Cooper-Hewitt National Design Museum and has been honored in 1995 as one of the ID Forty, ID Magazine's selection of America's leading design innovators.Lucille studied at California College of the Arts and holds an MFA in Design from Cranbrook Academy of Art.

subset: commoncrawl


text:
Kayla Shapero – GMOs: Proceed With Caution, But Proceed – February 22, 2012
It is true that genetic modification of plants may have the tendency to start controversial murmurs or perhaps even some rowdy protesting, but it also has the potential to help alleviate problems like malnutrition and environmental pollution.
First, a question for you the reader. What comes to mind when I say canola oil to you? You probably think of baking something sweet in an oven or cooking up something tasty in a pan. You may have even thought of how canola oil is one of the healthiest oils one can cook with. However, you probably didn't think of how canola is a cultivar or a plant that is a product of the controlled breeding and growth of two plants (American Heritage), a process called selective cross-breeding.
Canola is the offspring of the rapeseed plant and the common field mustard and if human manipulation of them had not taken place we would not have that tasty, healthy oil that we have come to know and love. In fact, before Canola oil was made, humans were using plain rapeseed oil – that is, until they realized its highly acidic properties caused heart problems.
At this point you may be wondering about the correlation between canola oil and genetically modified plants. Genetically modified plants, or transgenic plants, fall into a category of plants called cultigens, and most cultigens are cultivars (e.g. Canola). I mentioned cultivars briefly earlier, but just to reiterate, as defined by the American Heritage Dictionary, cultivars are plants created by the controlled cross-breeding and cultivation of plants that would not necessarily breed again and again under normal circumstances.
Essentially, transgenic plants are an accelerated or more direct version of selective cross-breeding in which specific genes may be spliced from one organism into another. The difference is instead of planting a bunch of seeds, allowing them to grow, breeding these plants together and then mass cultivating their offspring, a plant may now be genetically modified by splicing its genes with that of a plant with similar properties and then grown.
Basically, what I am getting at is that canola oil was man-made with the intention to create oil that was safer for human consumption than the rapeseed oil that was naturally occurring and popular in the past, and we succeeded with flying colors. Humans have been tampering with their surroundings since the beginning of time, and why not? We would be most ill-equipped if we didn't use our brains to help us craft tools to adapt to our ever-changing world.
However, we are quite crafty beings, and a little too successful for our own good. In our callous desperation to reach the top, we have overpopulated the world to the point that we can't feed everyone, and have created so many machines to make our lives easier that we have polluted the Earth at the expense of the environment we live in. Without embracing our gift for adaptation, we will not be able to carry on in life with such continued growth.
Genetically modified plants may not be able to single-handedly solve hunger problems, but transgenic plants may be manipulated to possess more nutrients than a naturally occurring plant would, and this could certainly benefit developing countries that have problems with malnutrition.
Malnutrition is a major problem, and vitamin deficiencies are not uncommon in parts of the world such as Asia. Rice is a main staple of many people's diets in the rural countries there, and typically rice is not very high in vitamin A. A deficiency in vitamin A can lead to problems such as blindness, but with transgenic plants, a new strain of rice called "golden rice" (Mellon and Risler) has been created that has much higher levels of vitamin A.
The Swiss Federal Institute of Technology is responsible for the creation of this new strain that contains an "unusually high content of beta-carotene (vitamin A)." With the help of genetically modified plants, people in Asia can once again "expect to retain normal eyesight."
Other advances in this technology include the introduction of plants that are resistant to pests. Much of a farmer's crop can be lost to bugs, bacteria, and viruses. Humans have coped with these obstacles by spraying their fields with harmful chemical pesticides that can be dangerous to people, nearby species of animals, and the environment. With the help of genetically modified plants, new strains of plants have been created that possess proteins within the plant itself that are harmful when consumed by insects, such as BT corn, which has been infused with genes from a strain of bacteria. The corn does not contain the bacteria itself, but genes from it that are harmful only to certain insects (ladybugs are unaffected).
The only problem that has arisen from this infusion is that this protein cannot be made to target particular bugs and while some bugs are resistant, there are some such as the Monarch butterfly that were not meant to be targeted and yet are still affected by it.
Opposition to this crop has been raised by a study on Monarch butterflies that demonstrated that pollen from these plants in high concentrations could be harmful to the larvae or caterpillars of this species.
However, this study, conducted by Professor John Losey of Cornell University, has since been proved to have been a flawed study and Prof. Losey himself has since said, "It doesn't seem like there's an immediate catastrophic risk to monarchs." This is because in his experiment, he dusted milkweed leaves with BT corn pollen at unrealistically high levels (Chrispeels & Sadava) and left those as the only source of food for the soon-to-be butterflies.
This experiment did not take normal field conditions into account. While milkweed is the only plant these caterpillars eat it does not grow in cornfields, but occasionally on the its outskirts. It more commonly grows by roadsides in the maize-belt and even so, only about "10 percent of the monarch butterfly habitat in the U.S maize belt is actually in maize fields" (Chrispeels & Sadava). The pollen from these plants is also too heavy to be carried very far and they shed pollen for only a margin of the time the butterflies are present in the corn-belt.
Ironically enough insecticides and pesticides also have no way of targeting specific bugs and since BT corn has been introduced, 30 percent of corn crops are now BT, the monarch butterfly population has been on the rise. Weather conditions during migration and logging regulations in Mexico (where the butterflies go in the winter) have proved to be more of an influence on this beautiful butterfly than the BT corn. This propagandized study has no factual evidence demonstrating the detrimental effects of such crops.
In essence, genetically modified plants will be helping the environment more than damaging it by lessening the amount of chemicals that we spray over our fragile ecosystems.
On the subject of our ecosystems, other oppositions to genetically modified crops include concerns that competing wild plants or weeds in the nearby areas will cross-breed with these genetically modified plants to create weeds that have the advantageous properties of the genetically modified plants. Essentially, these concerns voice fear that genetically modified plants will be introducing the development of new super-weeds to the environment or ecosystems, however:
"…hybridization between different species is extremely uncommon and it has never been observed between distantly related species. A tomato won't cross with a potato, even though they are both members of the nightshade family. Yet the GE opponents would have us believe that just about any plant can hybridize with any other." (Whitman)
Basically, it is highly uncommon for a plant to hybridize with another unless the plants share very similar properties. It is very rare to find plants in the wild environment that share such a close classification with transgenic plants, and therefore a hybridization between such plants to create a super-weed is not necessarily impossible, but it is highly improbable.
Not only can genetically modified plants help us with our hunger problems or malnutrition, but they have the potential to help clean up the environment that we have been polluting. Plants such as the poplar tree have been known to pull heavy metal pollutants from the soil (Whitman). They take these pollutants and convert them either to plant matter that can be utilized by the plant, or it converts these chemicals into something harmless that it then releases back into the atmosphere. The only hangup is that this plant does this at an extremely slow rate. However, with genetic modification, we can make this plant perform this function at an increased rate. This will help pull some of the harmful pollutants from the soil that we have introduced.
Perhaps the biggest opposition to genetically modified plants though comes from the general populace's own inherent fear that corporations such as Monsanto will be splicing genes into our food that could be dangerous to us. This fear has been worsened by the fact that the FDA does not require produce to be labeled as a genetically modified product since the FDA considers genetically modified plants to be "substantially equivalent to unmodified natural foods." (Whitman).
However, the FDA is not the only regulatory organization that has standards. Also, under the USDA, a program called BRS has been created to regulate genetically modified plant and animal organisms. These organizations and programs ensure that genetically modified organisms are as safe for human consumption as their naturally bred counterparts. For example, "When scientists realized a gene from Brazil nuts they were planning to splice into soybeans might sicken people harboring allergies to nuts, they discontinued the experiment. Similarly, when other researchers discovered that a protein in one type of GM corn might be allergenic, regulators approved that corn only for animal feed" (Mellon & Risler).
Transgenic plants have many potential ways to benefit our society. Not only are these plants capable of helping us solve hunger problems we have created for ourselves, but they are also capable of helping cleanse the environment we have been polluting with chemicals for our short-term convenience. Also, many concerns raised by environmental activists are rooted in propagandized statements based on no factual evidence.
If we were to fully embrace the science we have discovered and really utilize it, many of the problems we have created for ourselves in our hasty desperation for convenience could be potentially alleviated.
Genetic modification may be a new science, but if we proceed with caution, it will be a useful ally.
Works cited
(1) Mellon, Margaret and Rissler, Jane. "Environmental Effects of Genetically Modified Food Crops—Recent Experiences." Food and Agriculture on Union of Concerned Scientists. 12-13 June 2003. Web. 4 October 2011. ucsusa.org/food_and_agriculture/science_and_impacts/impacts_genetic_engineering/environmental-effects-of.html
(2) Whitman, Deborah B. "Genetically Modified Foods: Harmful or Helpful?" Discovery Guides at ProQuest. April 2000. Web. 4 October 2011. csa.com/discoveryguides/gmfood/overview.php#n1
(3) Briggs, Helen. "The Biotech Debate: the Monarch Butterfly." BBC News Online. 27 April 2001. Web. 17 October 2011. news.bbc.co.uk/2/hi/science/nature/1298397.stm
(4) Chrispeels, Maarten J. and Sadava, David E. Plants, Genes, and Crop Biotechnology. Sudburry: Jones and Bartlett Publishers, 2003. Print.
(5) Sprowles, Amy. Email Interview. 19 October 2011.
(6) "Cultivar." The American Heritage Science Dictionary. 2005. Print.
Kayla Shapero is a student at Humboldt State University currently earning a Biology major.


text:
You might also like
in Bonaire, GA
- $14
Verified per hourTaco Bell • 1h ago Just posted
- $14
Verified per hourTaco Bell • 1h ago Just posted
- $14
Verified per hourTaco Bell • 7d ago Urgently hiring
- $14
Verified per hourTaco Bell • 7d ago Urgently hiring
- $9.00-$10.00
Verified per hourSubway Franchisee • 7d ago
- $11
est. per hourSubway Franchisee • 7d ago
- $11
est. per hourSubway Franchisee • 30d ago
Restaurant Biscuit Maker/Baker
|Full-time, Part-time
| 99 Sandy Run Road
Bonaire, Georgia
About this job
At Capstone Restaurant Group, we are dedicated to the fast food industry and are independently owned and operated as a franchisee in the CKE Restaurant System. We are always searching for talented Team Members, at all levels, that are interested in growing with us.
As a Team Member, you are the energetic and warm smile that provides great hospitality to our guests. Whether you are greeting and serving our guests or preparing quality food products in a clean, pleasant, and safe environment, you get great satisfaction from demonstrating a high level of integrity in all that you do!
When you join the Capstone Restaurant Group Team, you will be given the tools to not only succeed on the job, but we will work with you to develop your skills to take advantage of the many promotion opportunities that we offer in all of our markets. We are an equal opportunity employer who takes pride in our diverse workforce. If you thrive in a fast-paced environment, where hard work and success is rewarded, and you are passionate about people, hospitality, and integrity, we want to talk to you!
We are willing to teach you all that you need to know to be successful with us. All that we ask is:
- You are at willing to work flexible hours
- You are at least 14 years old
- You have a great attitude and will value our Guests and fellow Team Members
- You strive to be dependable and reliable and always act with Integrity
WHAT MORE COULD YOU ASK FOR? We offer a Pay for Performance Plan that creates growth, development and more pay! In addition, we offer flexible scheduling, part-time and full-time opportunities, competitive pay and benefits, referral bonuses, meal discounts, scholarship opportunities, and tuition reimbursement!
To learn more about Capstone Restaurant Group, go to www.capstonerestaurants.com. To learn more about the Hardee's Franchise, go to www.hardees.com.
Note: This job posting is not intended to be an exhaustive list of all duties, responsibilities or qualifications with the job.
Capstone Restaurant Group is an equal opportunity employer.
I understand and acknowledge that Capstone Restaurant Group is an independently owned and operated franchisee of Hardee's Restaurants LLC and, if I am hired, Capstone Restaurant Group will be my employer, not Hardee's Restaurants. Further I understand and acknowledge that Capstone Restaurant Group LLC is not acting as an agent for Hardee's Restaurants or any of its affiliates.


text:
Ephesians 1
Bible Study
The Bible
About Us
Paul, apostle of Jesus Christ by God's will, to the saints and faithful in Christ Jesus who are at Ephesus.
Grace to you and peace from God our Father, and [the] Lord Jesus Christ.
Blessed [be] the God and Father of our Lord Jesus Christ, who has blessed us with every spiritual blessing in the heavenlies in Christ;
according as he has chosen us in him before [the] world's foundation, that we should be holy and blameless before him in love;
having marked us out beforehand for adoption through Jesus Christ to himself, according to the good pleasure of his will,
to [the] praise of [the] glory of his grace, wherein he has taken us into favour in the Beloved:
in whom we have redemption through his blood, the forgiveness of offences, according to the riches of his grace;
which he has caused to abound towards us in all wisdom and intelligence,
having made known to us the mystery of his will, according to his good pleasure which he purposed in himself
for [the] administration of the fulness of times; to head up all things in the Christ, the things in the heavens and the things upon the earth; in him,
in whom we have also obtained an inheritance, being marked out beforehand according to the purpose of him who works all things according to the counsel of his own will,
that we should be to [the] praise of his glory who have pre-trusted in the Christ:
in whom
also [have trusted], having heard the word of the truth, the glad tidings of your salvation; in whom also, having believed, ye have been sealed with the Holy Spirit of promise,
who is [the] earnest of our inheritance to the redemption of the acquired possession to [the] praise of his glory.
also, having heard of the faith in the Lord Jesus which [is] in you, and the love which [ye have] towards all the saints,
do not cease giving thanks for you, making mention [of you] at my prayers,
that the God of our Lord Jesus Christ, the Father of glory, would give you [the] spirit of wisdom and revelation in the full knowledge of him,
being enlightened in the eyes of your heart, so that ye should know what is the hope of his calling, [and] what the riches of the glory of his inheritance in the saints,
and what the surpassing greatness of his power towards us who believe, according to the working of the might of his strength,
[in] which he wrought in the Christ [in] raising him from among [the] dead, and he set him down at his right hand in the heavenlies,
above every principality, and authority, and power, and dominion, and every name named, not only in this age, but also in that to come;
and has put all things under his feet, and gave him [to be] head over all things to the assembly,
which is his body, the fulness of him who fills all in all:
Previous Page
• Ephesians 1 •
Next Page
Ephesians Chapters
Ephesians Chapter 1 (Darby Translation)


text:
I'm multidisciplined freelance designer specialise in rich interactive experiences for web. If you've got an exciting project, get in touch with me!
I'm award winning desiger. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
Featured Site + #1 Best of the best


text:
BERLIN- The nascent Berlin Performing Arts Center (BPAC) will have to look elsewhere for seed money, after the Worcester County Commissioners this week declined to assign the $200,000 requested to the project.
BPAC supporters had hoped to use the money from the county to get work begun on the $2.5 million project.
"It's not going to make or break the project. It just would have enabled us to build it at the least expensive time," said Patti Miller, Chair of the BPAC Research Committee. "It's taken years and years of research and evolution to this point. The timing was wrong for them with budget restraints, and their fear of adding anything new to the budget."
The commissioners made their decision on the performing arts center funding during budget deliberations on Wednesday.
"Things were just very, very tight," said Commissioner Louise Gulyas of the county's budget situation.
The commissioners have been saying for months that they would not fund new programs, and they stuck to that principle this week during budget deliberations. Although the commissioners support the concept, and in fact have wanted to pursue it for a decade, they decided against giving BPAC even a small amount of seed funds.
"The money is just not there. We had no frills," Gulyas said.
Commission president Virgil Shockley agreed there was just no room in the budget for the project this year. "You have a limited amount of money and limited choices," he said.
If timing is everything, than it wasn't in the cards for the BPAC seed money this year "Everyone thought it was a great idea. It's something we really need in Worcester County," said Commissioner Bud Church. "We didn't have any extra money. It just really wasn't the year to give them anything."
There was no money set aside for the performing arts center, Shockley said, but there was also no money put aside for the north end senior center, for example, or a sewer line to Showell Elementary School, despite the age of its septic system.
Miller said the project is still on track despite the delay. "It's going to move forward," she said. "There are way too many people in the community who would like that space to work out of or who would like that asset in our community."
The BPAC organizers will regroup and explore other funding options like grants, other local governments, and private fundraising.
"It's destined to be part of our community eventually," Miller said. "We're optimistic. We have nothing but time."


text:
View source for Chat:Ru/2021-12-24
Jump to navigation Jump to search
You do not have permission to edit this page, for the following reasons:
- The action you have requested is limited to users in one of the groups: Users, Bots, Administrators.
- You do not have permission to edit pages in the Chat namespace.
You can view and copy the source of this page.
Return to Chat:Ru/2021-12-24.


text:
17 Brus Corner
Florists , Wedding, Flowers, Bouquet, Special occasion, Silk Flower arrangements
Report a problem with this listing
We are a florist in Hartlepool, we do flowers for all occasions.
For all those special occasions and all those special people in your Life.
Testimonials are curated by Florians Florist and are not independently reviewed or verified.
"Valentine's box was beautiful. She was impressed, that's all I'll say! Thank you!"
Mike on 14 February 2014
"Danielles flowers from jack were absoloutely gorgeous"
Lesley on 15 February 2014
"Thank you so much for delivering my parents a gorgeous bunch of flowers for there anniversary. Looking forward to my wedding flowers now"
Janet on 6 September 2013
"Thank you so much for the amazing flowers you done for my family. My dad would of loved them. Thank you so much xx"
Sue on 2 November 2012
Monday to Friday
09:00 to 17:00
09:00 to 13:00


text:
The 30-day Wellness Guide:
more strength and vitality in your everyday life
It's possible to feel well in body and soul. You can take simple steps in different
areas within a few weeks to achieve a noticable improvement in your feeling
of wellbeing. We'll gladly support you!
Make further improvements to your feelings about your life. Our tips and tricks will be there to support you.
"An inability to notice our true feelings,
leaves us at their mercy."
Then join us in our Magnetix 30-day Wellness Guide for body and soul!
Every week, you will receive weekly exercises by email in the following areas: Healthy eating, physical wellbeing, self-awareness, appearance.
These will provide tangible support in making significant improvements to your attitude to life. No matter how well you're feeling today. We remind you every day to complete the exercises.
Sometimes a little friendly reminder is just what you need, isn't it?
And this is how the 30-day Wellness Guide works: you will receive by email
Every week a
weekly exercise
Every day a friendly
reminder, to look after
Order the '30-day Wellness Guide' email newsletter free of charge here


text:
Patch Tuesday is here, and I'd like to draw your attention to a broader policy decision Microsoft will be deploying next Patch Tuesday (October).
The strength of digital certificates is something I frequently write about here on Naked Security because I believe we all too often fall back to the lowest common denominator. Microsoft's market dominance means that, like it or not, they are somewhat responsible for establishing the minimum accepted practice.
Beginning in October, Windows computers consuming updates directly from Microsoft will no longer accept digital certificates that are signed with RSA keys smaller than 1024 bits.
This includes SSL certificates, Authenticode code signing certificates, email certificates, and any other certificates validated by the Windows Crypto APIs.
Why is this so important? It may break old applications, but it sets a new minimum standard that everyone should have adopted long ago.
The problem is many organizations got stuck in time and have not increased their key strength as flaws have been found and computing power has increased.
512-bit RSA keys were factored in 1999, while RSA 768 was factored in 2009. The reasonable conclusion is that these ciphers are no longer safe from snooping and need to be retired.
If you are an organization that still uses these keys, you may need to hold off on deploying this update, but is that really a good idea?
Perhaps this is a blessing in disguise, as anything you are "protecting" with weak RSA certificates isn't in fact protected at all. You ought to have fixed this situation, and the Microsoft update offers a golden opportunity if you haven't already done so.
If the data really *does* need protection it is time to raise the bar. 1024 bits is nice, but realistically there is no good reason not to bump it up to 4096. If it isn't sensitive to begin with, why are you using public key cryptography? It's needless complexity.
The way I like to think of it is similar to the way I think about people using WEP to protect their wireless networks. If an access point is unprotected, I assume that is intentional.
If it is protected with WPA2, I assume whoever controls it wants privacy and security. If it is protected with WEP, I assume that they want privacy and security and have no idea that they don't have it.
Don't be a WEP. Wave goodbye to keys <1024 bits with me and sail away into a more secure future.
Shield with check mark image courtesy of Shutterstock.


text:
3 New Teaching Methods Improve the Educational Process
We've updated this post with some newer, more useful and up-to-date information. Check out 5 New Teaching Methods Improving Education!
By Sonia Jackson
The traditional "chalk and talk" method of teaching that's persisted for hundreds of years is now acquiring inferior results when compared with the more modern and revolutionary teaching methods that are available for use in schools today. Greater student interaction is encouraged, the boundaries of authority are being broken down, and a focus on enjoyment over grades is emphasised.
As teachers, it's necessary to be able to teach and remain engaging. It puts a greater level of responsibility on creating lesson plans that truly work. Here are three teaching methods that are making an impact.
Spaced Learning
Teachers have reported amazing results when it came to spaced learning. Spaced Learning is a learning method in which the condensed learning content is repeated three times, with two 10-minute breaks during which activities such as physical activities are performed by the students – I think, that PE and lessons can be combined.
Spaced learning involves encouraging students to quickly switch through activities. For example, providing ten minutes of knowledge on the nervous system with a PowerPoint presentation and then having 15 minutes of basketball would be the way to get the better grades.
The results don't lie and the creators of the system at Monkseaton High School in Tyne and Wear have reported that it does work. They claim that it's more effective than simply teaching students by utilising traditional methods for four hours.
The key is in the brain cells. It helps them to create the connections that they need to actually remember the knowledge. Furthermore, it has the additional benefit of allowing people to relax. If they are compressing sections of the syllabus into such small sections then there's no time to worry. It's all about the learning before moving on to another session of activity.
Flexible Fridays
Sometimes conventional lesson blocks just don't work as every student is different and they all have their problematic subjects. The concept of Flexible Fridays is that an in-depth session of a subject can be acquired by simply having a whole day of mathematics or some other subject.
At Flexible Fridays lessons a teacher try to help each student to study and learn what is the most difficult for him/her personally. Somebody repeats, somebody learns. It makes it more convenient for students as now they can focus on one thing while in school. It means that students don't have a breaking point by spending hours struggling with a subject along at home.
Teachers also find it easier as they can keep their lesson plans and simply go over them again with a more personal touch. Flexible Friday lessons are more in-touch with students and gives focused study time that can help students grasp difficult concepts.
Teachers are also able to aid students by simply having fast-track weeks. Having a whole week of mathematics or English can help students to get through the subjects in a shorter amount of time.
It's good news for teachers and students alike because even though a lesson lasts an hour it could actually lose up to 25 percent of its designated time. There's the preparing for class and packing away to take into account, and students are not always the quickest at performing these tasks.
Teacher should choose what method is more appropriate for his/her students: spaced learning or Flexible Fridays.
Under a new teaching method called "engagement" students are urged to engage with the real world, analyse everything that happens in different life spheres (not only internship but also economical, business, social spheres, etc.). Business studies are where this new focus of engagement occurred at the Leasowes Community College in Dudley.
Instead of conventional teaching methods, students were taken to visit local businesses where they were able to witness how the knowledge that they were learning applied to the real world.
Multiple days were set aside for this practice and all students were required to wear business suits in order to attend. The idea is to get students engaged and to connect their learning to the real world. If teachers can show them how what they are teaching connects to the real world then their own brain cells are going to connect them and associate them.
The results are there for all to see because before this new method was introduced only 40 percent of students achieved grades of A-C across both years 10 and 11. Under the new teaching method the institution reported that the numbers had shot up to a massive 91 percent of students achieving A-Cs in years 10 and year 11.
New methods of teaching have the purpose to improve the quality of education and involve students in educational process. Innovations mean a progress and development.
Sonia Jackson writes for www.custom-essay-writing.org.
Photo Courtesy of BigStock.


text:
This morning, in our book spotlight, we are featuring a new, young adult, fantasy novel from Jen Castleberry. Check out A Wild and Unremarkable Thing, learn about the author and enter for a chance to win a $15 Amazon gift card in the book tour giveaway at the end of this post.
A Wild and Unremarkable Thing
by Jen Castleberry
Genre: YA Fantasy
Fifteen years have passed since a Fire Scale scorched Cayda's village. Fifteen years of beatings, of bare kitchen cupboards and sloppy swordplay. Fifteen years of biting her lip for her father's cane while her younger sisters did the same for the grimy patrons of the village brothels. Fifteen years of staring steadfastly after beauty in an increasingly ugly world.
Now, with hair shorn and breast bound, Cayda marches into the Summer Alps as Cody, a hopeful Champion seeking a dragon-slayer's reward, with the full weight of her family's survival on her shoulders.
But the road between poverty and prosperity is rife with beasts, betrayals, and baser temptations. Sensible Cayda soon discovers that she is not the only Champion with her eye on the prize, or the only one wearing a disguise.
With monsters, gods, and royalty hot on her heels, Cayda must ask herself if victory is worth sacrificing her identity for – or her life.
A Wild and Unremarkable Thing pits girl against dragon in a stunning blend of Greek mythology and medieval lore. Readers will not quickly forget the diverse cast or the thrilling, sexy ride!
Jen Castleberry resides in Virginia Beach with her husband and pets. Her background is in Communications and Animal Welfare. All of her pets are named after superheroes!
Follow the tour HERE for exclusive excerpts, guest posts and a giveaway!


text:
Violent forced evictions in China are on the rise as local authorities seek to offset huge debts by seizing and then selling off land in suspect deals with property developers, Amnesty International said Oct. 11. In a new report, "Standing Their Ground" (PDF), Amnesty International highlights how forced evictions—a longstanding cause of discontent within China—have increased significantly in the past two years in order to clear the way for developments. Local governments have borrowed huge sums from state banks to finance stimulus projects and now rely on land sales to cover the payments. This has resulted in deaths, beatings, harassment and imprisonment of residents who have been forced from their homes across the country in both rural and urban areas. Some were in such despair they set themselves on fire in drastic protests of last resort.
However, China's ruling Communist Party continues to promote local officials who deliver economic growth, regardless as to how it is achieved, Amnesty charges. Land re-development, at whatever cost—whether for new roads, factories or residential complexes—is seen as the most direct path to visible results. "The Chinese authorities must immediately halt all forced evictions. There needs to be an end to the political incentives, tax gains and career advancements that encourage local officials to continue with such illegal practices," said Nicola Duckworth, senior director of research at Amnesty International.
Of 40 forced evictions that Amnesty International examined in detail as part of the research, nine culminated in the deaths of people protesting or resisting eviction. In one case a 70-year-old woman, Wang Cuiyan, was buried alive by an excavator on March 3, 2010 when a crew of about 30 to 40 workers came to demolish her house in Wuhan city, Hubei province.
Local officials continue to sanction or turn a blind eye to the harassment of residents by developers using ruthless tactics to force people out of their homes and sell their rights to land-use. Proper consultation or notice as required under international law as well as adequate alternative housing are seldom given and any compensation falls far short of the true market value. Residents come under concerted campaigns including the cutting off of essential services like water and heating. Civil servants who oppose land deals often face reprisals.
Local governments and property developers frequently hire thugs wielding steel rods and knives to rough up residents. Housing rights activists, lawyers and academics in China confirmed Amnesty International's finding that the police hardly ever investigate such crimes.
One violent example occurred on April 18, 2011 when a few hundred men entered Lichang village in Jiangsu province and attacked farmers to force them off their land. About 20 women from the village were dragged away and beaten. On June 15, 2011, police in Wenchang city, Sichuan province even took custody of a 20-month old baby and refused to return him until his mother signed an eviction order.
People who stage resistance to forced evictions often end up in prison or in Re-education Through Labour (RTL) centers. In one case, authorities in Shandong province assigned Li Hongwei, a victim of forced eviction, to 21 months RTL detention for delivering two protest speeches in a plaza in May last year.
The report also noted use of forced sterilization as a form of retribution against those protest evictions. In Hexia township Jiangxi province, a woman was beaten and forced to undergo sterilization, on May 17, 2011 after she had petitioned the authorities about her eviction, while other residents that accompanied her were beaten.
The lack of independence in Chinese courts means those that seek to challenge an eviction or seek redress have little hope of gaining justice. Lawyers are also reluctant to take on such clients for fear of the repercussions. With no access to justice some have turned to violence or even self-immolation as a last resort. Amnesty International collected reports of 41 cases of self-immolation from 2009-2011 alone due to forced evictions. That compares to fewer than 10 cases reported in the entire previous decade.
Forced evictions remain one of the greatest issues of popular discontent within China. Premier Wen Jiabao has acknowledged the gravity of the situation and there has been some progress towards protecting people against forced evictions in line with international law and standards. For the first time, new regulations adopted in 2011 state that compensation for homeowners must not be lower than market value and outlawed the use of violence.
However, these laws and regulations still fall far short of the required standards and apply only to city dwellers, Amnesty says. Rural communities remain vulnerable to forced evictions, particularly those close to urban areas. With urbanization happening so quickly around them, and compensation based on the agricultural value rather than the true market value, farmers are often priced out of the communities they have lived in their whole lives. Another major weakness in the latest regulations is that they only provide protections for homeowners, overlooking the rights of tenants.
Forced evictions—the removal against their will of individuals, families or communities from the homes or the land they occupy without access to legal or other protections—are banned under international law. (AI, Oct. 11)
See our last post on forced sterilization and the peasant struggle in China.


text:
Thursday, March 4, 2010
CARDS 2010 January Publications
19 comments:
what elegant design.beautyful cards!I love them!Thank you for inspiration!ReplyDelete
celine from france.
All of them are gorgeous Maile. I know, I just love the chocolate ink on kraft cardstock, one of my all time fav combos.ReplyDelete
I remember admiring these in the January CARDS Maile! Each one of them stunning!!ReplyDelete
Congrats on your publication, Maile! Love the gorgeous colors and your style is just heavenly! I also want to share two similar cards made my college daughter using my one and only PTI set. http://virginialusblog.blogspot.com/2010/02/stephanies-bicycle-cards.html Thanks for the inspiration!ReplyDelete
Love them all Mailes :)ReplyDelete
WOW what a beautiful bunch of cards! I love them all of course but your In Bloom one has me drooling! I wish you'd stop using that set because I haven't got it LOL!!!ReplyDelete
Thanks so much for your really, really, REALLY, sweet comment! You've totally made my day, no, my week :D
yummy yummy cards, Mailes!! fabulous designs as always!1 love hem all! =)ReplyDelete
These are all incredible creations!!!ReplyDelete
I am in love with the color combo. for the bicycle card. In Bloom has become one of my fast favorites and I love what you have done with that set. Great group of cards. You deserve to be published. What talent. Thank you for leaving me a comment on my blog that was so very nice of you.ReplyDelete
these are AWESOME!!!!!ReplyDelete
Yup, what Laura said!! :) Totally, positively AWESOME! :)ReplyDelete
Woopsie! My keyboard is sparking from all of the drool that just happened! :o) These cards are AMAZING - just like the girl who made 'em! YOU rock, sweet girl!ReplyDelete
WOW, with so many cards for publication, they should dedicate a whole issue to you soon!ReplyDelete
I have got to take a deep breath and start submitting some of my cards, too!
Adorable! I love that stamp set. It's been on my wishlist for a while, but it's currently unavailable at Paper Trey. I just love what you did with them! Very unique spin.ReplyDelete
So great as always!!! What punch did you use for the cupcake embossed scallop? :)ReplyDelete
Georgous cards!!!ReplyDelete
I love them all but the firt is my favorite...
Awesome cards. It's fun to seeing your cards in "print". I have a card on my blog today that was inspired by one of your cards from the March/April Papercrafts issue. Check it out.ReplyDelete
What a bunch of fabby pub'd cards!!! Love all your clean details that make each one special....thanks for sharing them, its so great to see them all together! :>ReplyDelete
Fantastic work (as usual)!!! Love the buttons for the bike tires!! So perfect! Congratulations on all of your publications!!ReplyDelete