[LLVMdev] LLVM frontend supporting arbitrary bit-width integral datatypes
ihusar
ihusar at fit.vutbr.cz
Wed Jun 24 05:47:10 PDT 2009
On Thu, 04 Jun 2009 22:55:04 +0200, Pertti Kellomäki <pertti.kellomaki at tut.fi> wrote:
> Hi Adam,
>
> John is right, the TCE stuff would be useful for you. Our
> compiler targets a processor template that the designer can
> populate pretty freely. The compiler then reads the architecture
> description and creates an LLVM backend on the fly.
>
> Please don't hesitate to get in touch with us if you have
> questions.
Hello,
thank you for your answers, in fact, the TCE project is quite similar to our project Lissom (http://www.fit.vutbr.cz/research/view_product.php.en?id=52¬itle=1), I will take a closer look at it.
One problem, I was trying to solve was, that I need to declare variables of let's say 5-bit width like 'i5 var',
the maximal bit-width may be limited to 64 bits. I need such variables to represent instruction's operands,
example is at the end this message.
For now, I did not find any usable compiler frontend.
First attempt was quite old Valen-C based on SUIF compiler which requires unavailable version of
SUIF and would be hard to make work.
Second attempt was SpecC reference compiler - as most of high-level language synthetizers, turns
arbitrary bit-width integers into C++ templates which makes it unusable.
Then few other attempts, but not much luck.
The conclusion is, that I will need to modify some compiler frontend by my own, propably the clang.
Please, if you have some info afout this or if anyone has already tried such thing, could you write it here?
Also, is there anything I should be aware of when modifing the clang? Are there some passes, that are
made only for the standard C datatypes?
Stuff like sizeof() and C pointer arithmetics can be forbidden integers which bit width is not divisible by 8.
Thank you
Adam
(I am posting this both to the llvmdev and clangdev, sry for possible spamming.)
Example of why do I need arbitrary bit-width integers:
I can extract from our architecture description language ISAC code, that for each instruction tells what it
does:
Syntax:
MIPS instrucion ADDDI
"ADDI" reg(0) "," reg(1) "," imm(2)
Semantics:
unsigned int gpregs[32];
void instr_direct_rri$op_addi$imm16$()
{
int op_arithm_imm = 0x08; {
int rt = 1; {
int rs = 28; {
short imm16 = imm_i16(2); //--- intrinsics, represents instruction's immediate operand
{
{
int simm = ((int)(imm16) << (32 - (16))) >> (32 - (16));
switch (op_arithm_imm)
{
//....
case 0x08:
case 0x09:
{if (rt != 0) gpregs[(rt)] = (( (((rs) != 0)?gpregs[(rs)]:0) ) + simm);};
break;
case 0x0A:
{if (rt != 0) gpregs[(rt)] = (( (((rs) != 0)?gpregs[(rs)]:0) ) < simm);};
break;
//....
}
}}}}}
}
Compile it with LLVM or any other compiler and get optimized code:
; ModuleID = 't2.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-unknown-linux-gnu"
@gpregs = common global [32 x i32] zeroinitializer, align 4 ; <[32 x i32]*> [#uses=2]
define void @"instr_direct_rri$op_addi$imm16$"() nounwind {
entry:
%tmp = tail call i16 @llvm.immread.i16.i32(i32 2) nounwind ; <i16> [#uses=1]
%shr = sext i16 %tmp to i32 ; <i32> [#uses=1]
%tmp10 = load i32* getelementptr ([32 x i32]* @gpregs, i32 0, i64 28) ; <i32> [#uses=1]
%add = add i32 %tmp10, %shr ; <i32> [#uses=1]
store i32 %add, i32* getelementptr ([32 x i32]* @gpregs, i32 0, i64 1)
ret void
}
This I can quite easily transform to instruction selection rule:
set(reg, add(reg, sext(32, imm)))
which is then used by compiler backend generator, so the code selector can then use instruction ADDI.
The problem is, that the only supported types now are i8, i16 and i32 (and floating in the future).
If the processor designer would like to have 12-bit operand, I need to turn it into 16-bit and
then the compiler would generate useless code for extension/truncation and
extracted code selection rule would not be correct.
More information about the llvm-dev
mailing list