How is c's const keyword translated when compiling c into llvm bytecode. I'm specifically interested in const pointer function arguments. Consider a function declared as follows in c: void f(const int* arg); When I examine f in llvm bytecode, how can I tell that arg is a pointer, whose contents can only be read, not written. Regards, Ryan
> How is c's const keyword translated when compiling c into > llvm bytecode.It isn't. You can verify this quite simply with the following test program: void a(const void *p) { } void b(void *p) { } $ clang --emit-llvm test.c ; ModuleID = 'foo' define void @a(i8* %p) { entry: %p.addr = alloca i8* ; <i8**> [#uses=1] %allocapt = bitcast i32 undef to i32 ; <i32> [#uses=0] store i8* %p, i8** %p.addr ret void } define void @b(i8* %p) { entry: %p.addr = alloca i8* ; <i8**> [#uses=1] %allocapt = bitcast i32 undef to i32 ; <i32> [#uses=0] store i8* %p, i8** %p.addr ret void } Now, I tried this with the gcc 4.0 frontend as well: $ gcc -c --emit-llvm test.c -o - | llvm-dis -o - ; ModuleID = '<stdin>' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" target triple = "i686-pc-linux-gnu" define void @a(i8* %p) { entry: %p_addr = alloca i8* ; <i8**> [#uses=1] %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] store i8* %p, i8** %p_addr br label %return return: ; preds = %entry ret void } define void @b(i8* %p) { entry: %p_addr = alloca i8* ; <i8**> [#uses=1] %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] store i8* %p, i8** %p_addr br label %return return: ; preds = %entry ret void } As you can see, with both C compilers the generated intermediate language is the same for both function a() and b().
Thanks for the help. I'm surprised that llvm doesn't preserve the const property. I thought that it was supposed to be useful for various compiler optimizations. Holger Schurig wrote:>>How is c's const keyword translated when compiling c into >>llvm bytecode. > > > It isn't. You can verify this quite simply with the following > test program: > > void a(const void *p) > { > } > > void b(void *p) > { > } > > > > $ clang --emit-llvm test.c > ; ModuleID = 'foo' > > define void @a(i8* %p) { > entry: > %p.addr = alloca i8* ; <i8**> [#uses=1] > %allocapt = bitcast i32 undef to i32 ; <i32> [#uses=0] > store i8* %p, i8** %p.addr > ret void > } > > define void @b(i8* %p) { > entry: > %p.addr = alloca i8* ; <i8**> [#uses=1] > %allocapt = bitcast i32 undef to i32 ; <i32> [#uses=0] > store i8* %p, i8** %p.addr > ret void > } > > > > Now, I tried this with the gcc 4.0 frontend as well: > > $ gcc -c --emit-llvm test.c -o - | llvm-dis -o - > ; ModuleID = '<stdin>' > target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" > target triple = "i686-pc-linux-gnu" > > define void @a(i8* %p) { > entry: > %p_addr = alloca i8* ; <i8**> [#uses=1] > %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] > store i8* %p, i8** %p_addr > br label %return > > return: ; preds = %entry > ret void > } > > define void @b(i8* %p) { > entry: > %p_addr = alloca i8* ; <i8**> [#uses=1] > %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] > store i8* %p, i8** %p_addr > br label %return > > return: ; preds = %entry > ret void > } > > > As you can see, with both C compilers the generated intermediate language > is the same for both function a() and b(). > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-- Ryan M. Lefever [http://www.ews.uiuc.edu/~lefever]
This property isn't preserved on the llvm ir, because const can always be cast away. If you want mod information, then I suggest using the aliasanalysis interface to get mod ref info for a call. -Chris http://nondot.org/sabre http://llvm.org On Aug 8, 2007, at 12:07 AM, "Ryan M. Lefever" <lefever at crhc.uiuc.edu> wrote:> How is c's const keyword translated when compiling c into llvm > bytecode. > I'm specifically interested in const pointer function arguments. > Consider a function declared as follows in c: > > void f(const int* arg); > > When I examine f in llvm bytecode, how can I tell that arg is a > pointer, > whose contents can only be read, not written. > > Regards, > Ryan > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Hi, I think I found a bug. I don't know if it's in upstream gcc or llvm-gcc4. int func() { const int *arr; arr[0] = 1; } $ llvm-gcc main.c -c; echo $? 0 $ gcc main.c -c main.c: In function 'func': main.c:4: error: assignment of read-only location The difference disappears when arr[0] is replaced by *arr. (I tried the above with gcc 4.1.2, 3.4.6, 4.0.3. (I don't have access to 4.0.1, off which llvm-gcc seems to be derived.) nikhil On 08/08/2007, Chris Lattner <sabre at nondot.org> wrote:> This property isn't preserved on the llvm ir, because const can always > be cast away. If you want mod information, then I suggest using the > aliasanalysis interface to get mod ref info for a call. > > -Chris > > http://nondot.org/sabre > http://llvm.org > > On Aug 8, 2007, at 12:07 AM, "Ryan M. Lefever" <lefever at crhc.uiuc.edu> > wrote: > > > How is c's const keyword translated when compiling c into llvm > > bytecode. > > I'm specifically interested in const pointer function arguments. > > Consider a function declared as follows in c: > > > > void f(const int* arg); > > > > When I examine f in llvm bytecode, how can I tell that arg is a > > pointer, > > whose contents can only be read, not written. > > > > Regards, > > Ryan > > _______________________________________________ > > LLVM Developers mailing list > > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >
I don't mean to be a pain, but I was thinking about this a bit more. Does gcc ignore the const keyword? If not, why has LLVM chosen to deviate from gcc with respect to the const keyword? If so, then why do we bother using const in LLVM API code? I'm just curious and wanted to understand the thinking behind not preserving const. Thanks, Ryan Chris Lattner wrote:> This property isn't preserved on the llvm ir, because const can always > be cast away. If you want mod information, then I suggest using the > aliasanalysis interface to get mod ref info for a call. > > -Chris > > http://nondot.org/sabre > http://llvm.org > > On Aug 8, 2007, at 12:07 AM, "Ryan M. Lefever" <lefever at crhc.uiuc.edu> > wrote: > > >>How is c's const keyword translated when compiling c into llvm >>bytecode. >> I'm specifically interested in const pointer function arguments. >>Consider a function declared as follows in c: >> >>void f(const int* arg); >> >>When I examine f in llvm bytecode, how can I tell that arg is a >>pointer, >>whose contents can only be read, not written. >> >>Regards, >>Ryan >>_______________________________________________ >>LLVM Developers mailing list >>LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-- Ryan M. Lefever [http://www.crhc.uiuc.edu/~lefever/index.html]