changeset 250:6ce7c7edee53

using extern setjmp if builtin is not available
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 17 Aug 2023 20:34:53 +0900
parents b3a488e1e1b4
children 289b6d909d63
files clang/include/clang/Parse/Parser.h clang/lib/Parse/ParseCbC.cpp
diffstat 2 files changed, 43 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/clang/include/clang/Parse/Parser.h	Sun Aug 13 12:24:34 2023 +0900
+++ b/clang/include/clang/Parse/Parser.h	Thu Aug 17 20:34:53 2023 +0900
@@ -2127,6 +2127,7 @@
 #ifndef noCbC
   StmtResult ParseCbCGotoStatement(ParsedAttributes &Attrs,StmtVector &Stmts);
   void CompileFromString(const char *str, StmtVector &CompoundStmts);
+  bool isBuiltinSetjmpDefined() ;
 #endif
   StmtResult ParseContinueStatement();
   StmtResult ParseBreakStatement();
--- a/clang/lib/Parse/ParseCbC.cpp	Sun Aug 13 12:24:34 2023 +0900
+++ b/clang/lib/Parse/ParseCbC.cpp	Thu Aug 17 20:34:53 2023 +0900
@@ -94,39 +94,6 @@
     };
 }
 
-
-/// goto with environment with out logjmp
-/// basic idea is prepare struct containes pointer to return value variable and stack pointer
-/// 
-/// int main() {
-///    struct __CbC_return {
-///      int* i;
-///      void* sp;
-//       void* fp;
-///    } ret; 
-//     int i;
-///    if (0) {
-//  _CBC_RETURN: 
-//        %fp = ret.fp;
-//        %rsp = ret.sp;
-//        i = *(ret.i); //?
-//        return i;
-//     }
-///    ret.i = &i;
-///    ret.sp = %rsp;
-//     ret.fp = %rfp;
-///    __code c(int i,void* env) = _CBC_RETURN;
-///    goto f(c, &ret);
-/// }
-/// 
-/// __code ret(int, void* env) {
-//      sp = env;
-//      %rax = 1;
-//      jmp _CBC_RETURN;
-/// }
-/// 
-///
-
 /// Prepare__retForGotoWithTheEnvExpr - Prepare __CbC_return, code segment for returning and some necessary statements.
 /// It is called when the parser find __return and statements are put into complex statement.
 /// 
@@ -137,11 +104,7 @@
 ///           __CbC_return = code_segment_for_return;
 ///           __CbC_return;
 ///         });
-///   code segment:
-///         __code ret(return_type retval, void *env){
-///           *(return_type)((struct __CbC_env *)(env))->ret_p = retval;
-///             longjmp((int*)(((struct __CbC_env *)env)->env),1);
-///         }
+
 ExprResult Parser::Prepare__retForGotoWithTheEnvExpr(){
 
   if (isVoidFunction()) { // error check : function type is void or not.
@@ -162,6 +125,7 @@
   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),Loc,"in compound statement ('{}')");
   StmtVector CompoundStmts; 
 
+  ConsumeAnyToken(); // eat the '__return'.
   // create code segment for return to C's function
   CreateRetCS(retcsII);
     
@@ -181,11 +145,24 @@
     CompoundStmts.push_back(innerRes.get());
   Sema::CompoundScopeRAII CompoundScope(Actions);
   CompoundStmtRes = Actions.ActOnCompoundStmt(Loc,Loc,CompoundStmts,true);
-  ConsumeAnyToken(); // eat the '__return'.
 
   return Actions.ActOnStmtExpr(getCurScope(),Loc, CompoundStmtRes.get(), Loc);
 }
 
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
+
+bool Parser::isBuiltinSetjmpDefined() {
+  IdentifierInfo *II = PP.getIdentifierInfo("__builtin_setjmp");
+  if (II != nullptr) {
+    int BuiltinID = II->getBuiltinID();
+    
+    if (BuiltinID != Builtin::BI__builtin_setjmp) 
+      return true;
+    }
+  return false;
+}
+
 /// Prepare__envForGotoWithTheEnvExpr - Prepare __CbC_environment, struct __CbC_env and some necessary statements.
 /// It is called when the parser find __environment and statements are put into complex statement.
 /// 
@@ -194,6 +171,7 @@
 ///         ({
 ///           volatile struct __CbC_env __CbC_environment;
 ///           jmp_buf env_buf;  --> int env_buf[64];
+///           extern int setjmp(jmp_buf);
 ///           return_type retval;
 ///           __CbC_environment.ret_p = &retval;
 ///           __CbC_environment.env = &env_buf;
@@ -207,6 +185,10 @@
 ///           void *ret_p,*env;
 ///         }
 
+//
+// Compile from String
+//   make sure to CosumeToken() before call this function.
+//
 void Parser::CompileFromString(const char *str, StmtVector &CompoundStmts){
   SourceLocation Loc = Tok.getLocation();
   Token TokSave = Tok;
@@ -259,7 +241,11 @@
     CompoundStmts.push_back(innerRes.get());
 
   ConsumeAnyToken(); // eat the '__environment'.
-  CompileFromString("int env_buf[64];",CompoundStmts); // 4*64 is enough for every arch right now
+  if (isBuiltinSetjmpDefined()) {
+      CompileFromString("int env_buf[64];",CompoundStmts); // 4*64 is enough for every arch right now
+  } else {
+      CompileFromString("int env_buf[64];extern int setjmp(void *);",CompoundStmts); 
+  }
 
   // __CbC_environment.ret_p = &retval;
   innerRes = CreateAssignmentStmt(__CbC_envII, retvalII, true, true, ret_pII);
@@ -522,7 +508,11 @@
   StmtResult InitStmt;
   Sema::ConditionResult Cond;
 
-  CondExp = LookupNameAndBuildExpr(CreateIdentifierInfo("__builtin_setjmp", Loc));
+  if (isBuiltinSetjmpDefined()) {
+      CondExp = LookupNameAndBuildExpr(CreateIdentifierInfo("__builtin_setjmp", Loc));
+  } else {
+      CondExp = LookupNameAndBuildExpr(CreateIdentifierInfo("setjmp", Loc));
+  }
   ExprVector ArgExprs;
   ExprResult __envExprRes = CondExp.get();
 
@@ -699,7 +689,7 @@
 /// CreateRetCS - Create code segment which is used for continuation with the environment.
 ///   create these codes:
 ///         __code ret(return_type retval, void *env){
-///           *(return_type)((struct CbC_environment *)(env))->ret_p = n;
+///           *(return_type)((struct CbC_environment *)(env))->ret_p = retval;
 ///             longjmp((void*)(((struct __CbC_environment *)env)->env),1);
 ///         }
 void Parser::CreateRetCS(IdentifierInfo *csName){
@@ -779,6 +769,11 @@
   ExprVector ArgExprs;
   CommaLocsTy CommaLocs;
   DeclSpec envDS(AttrFactory);
+
+  if (! isBuiltinSetjmpDefined()) {
+      CompileFromString("extern void longjmp(void *,int);",FnStmts); 
+  }
+
   IdentifierInfo *structName = CreateIdentifierInfo(__CBC_STRUCT_NAME, Loc);
   setTST(&envDS, DeclSpec::TST_struct, structName);
 
@@ -824,7 +819,11 @@
     FnStmts.push_back(innerR.get());
 
   ExprResult ljExpr,ljLHS;
-  ljExpr = IIToExpr(CreateIdentifierInfo("__builtin_longjmp",  Loc), tok::l_paren);
+  if (isBuiltinSetjmpDefined()) {
+      ljExpr = IIToExpr(CreateIdentifierInfo("__builtin_longjmp",  Loc), tok::l_paren);
+  } else {
+      ljExpr = IIToExpr(CreateIdentifierInfo("longjmp",  Loc), tok::l_paren);
+  }
   ExprVector ljArgExprs;
   DeclSpec ljDS(AttrFactory);
   setTST(&ljDS, DeclSpec::TST_struct, structName);